/* Reusable UI pieces. Colours come from the tokens in base.css / the theme. */ /* ---------------------------------------------------------------- panels */ .panel { display: flex; flex-direction: column; gap: var(--gap); padding: 1rem; background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius); } .panel__head { display: flex; align-items: center; justify-content: space-between; gap: var(--gap); flex-wrap: wrap; } .panel__title { font-size: 1.05rem; } .hint { color: var(--text-muted); font-size: 0.875rem; } .banner { margin: 0; padding: 0.6rem 1rem; background: var(--danger); color: #fff; text-align: center; } /* ----------------------------------------------------------------- icons */ .icon { flex: none; width: var(--icon-size); height: var(--icon-size); object-fit: contain; border-radius: 6px; } .icon--placeholder { display: block; background: var(--placeholder); } /* --------------------------------------------------------------- buttons */ .btn { display: inline-flex; align-items: center; justify-content: center; flex-wrap: wrap; column-gap: 0.5rem; min-height: 44px; padding: 0.5rem 1rem; background: var(--surface-2); border: 1px solid var(--border); border-radius: var(--radius); cursor: pointer; text-align: center; touch-action: manipulation; user-select: none; -webkit-tap-highlight-color: transparent; } .btn small { color: var(--text-muted); font-size: 0.8rem; } .btn:hover:not(:disabled) { border-color: var(--accent); } .btn:active:not(:disabled) { transform: translateY(1px); } .btn:disabled { opacity: 0.5; cursor: not-allowed; } .btn--primary { background: var(--accent); border-color: var(--accent); color: var(--accent-contrast); font-weight: 600; } .btn--primary small { color: inherit; opacity: 0.85; } .btn--big { min-height: 84px; flex-direction: column; font-size: 1.15rem; } .btn--wide { width: 100%; justify-content: space-between; } .btn--ghost { background: transparent; } .btn--danger { border-color: var(--danger); color: var(--danger); } .btn--square { width: 44px; padding: 0; font-size: 1.25rem; } .btn--buy { flex-direction: column; min-width: 7.5rem; align-self: center; } .btn__label { font-weight: 600; } /* ----------------------------------------------------------- form fields */ .field { display: flex; flex-direction: column; gap: 0.15rem; } .field__label { color: var(--text-muted); font-size: 0.75rem; } select, .price__input, .textarea { min-height: 44px; padding: 0.4rem 0.6rem; background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius); } .textarea { width: 100%; min-height: 0; font-family: ui-monospace, Menlo, Consolas, monospace; font-size: 0.8rem; resize: vertical; } .row { display: flex; flex-wrap: wrap; gap: var(--gap); } .badge { display: inline-block; padding: 0.05rem 0.5rem; background: var(--surface-2); border-radius: 999px; color: var(--text-muted); font-size: 0.75rem; font-weight: 500; } /* -------------------------------------------------------------- overview */ .tiles { display: grid; gap: var(--gap); grid-template-columns: repeat(auto-fit, minmax(10rem, 1fr)); } .tile { display: flex; align-items: center; gap: var(--gap); padding: 0.75rem; background: var(--surface-2); border-radius: var(--radius); } .tile--primary { outline: 2px solid var(--accent); } .tile__label { display: block; color: var(--text-muted); font-size: 0.8rem; } .tile__value { display: block; font-size: 1.5rem; font-variant-numeric: tabular-nums; line-height: 1.2; } .stats { display: grid; gap: 0.25rem var(--gap); grid-template-columns: repeat(auto-fit, minmax(9rem, 1fr)); } .stats > div { display: flex; flex-direction: column; } .stats dt { color: var(--text-muted); font-size: 0.8rem; } .stats dd { font-variant-numeric: tabular-nums; font-weight: 600; } /* ----------------------------------------------------------------- price */ .price { display: flex; flex-direction: column; gap: 0.5rem; } .price__label { color: var(--text-muted); font-size: 0.8rem; } .price__row { display: flex; gap: 0.5rem; } .price__input { flex: 1; min-width: 0; text-align: center; font-size: 1.25rem; font-variant-numeric: tabular-nums; } .price__slider { width: 100%; height: 32px; /* easy to grab on touch screens */ accent-color: var(--accent); } /* ------------------------------------------------- generators & upgrades */ .cards { display: flex; flex-direction: column; gap: var(--gap); } .card { display: flex; align-items: flex-start; gap: var(--gap); padding: 0.75rem; background: var(--surface-2); border-radius: var(--radius); } .card__body { flex: 1; min-width: 0; } .card__title { display: flex; flex-wrap: wrap; align-items: center; gap: 0.5rem; font-size: 1rem; } .card__desc, .card__meta { color: var(--text-muted); font-size: 0.85rem; } .card__meta { font-variant-numeric: tabular-nums; } /* Narrow phones: the buy button drops under the text. */ @media (max-width: 479px) { .card { flex-wrap: wrap; } .card__body { flex-basis: calc(100% - var(--icon-size) - var(--gap)); } .btn--buy { flex: 1 0 100%; flex-direction: row; justify-content: space-between; } } .segmented { display: inline-flex; border: 0; gap: 0.25rem; } .segmented label { cursor: pointer; } .segmented input { position: absolute; opacity: 0; pointer-events: none; } .segmented span { display: inline-flex; align-items: center; min-height: 36px; padding: 0 0.7rem; background: var(--surface-2); border: 1px solid var(--border); border-radius: var(--radius); font-size: 0.85rem; } .segmented input:checked + span { background: var(--accent); border-color: var(--accent); color: var(--accent-contrast); } .segmented input:focus-visible + span { outline: 3px solid var(--accent); outline-offset: 2px; } /* ---------------------------------------------------------------- dialog */ .dialog { width: min(40rem, calc(100vw - 2rem)); max-height: calc(100vh - 2rem); padding: 0; background: var(--surface); color: var(--text); border: 1px solid var(--border); border-radius: var(--radius); } .dialog::backdrop { background: rgb(0 0 0 / 0.55); } .dialog__body { display: flex; flex-direction: column; gap: var(--gap); padding: 1rem; } .dialog__subtitle { margin-top: 0.5rem; font-size: 0.95rem; } /* ---------------------------------------------------------------- toasts */ .toasts { position: fixed; right: 1rem; bottom: calc(1rem + env(safe-area-inset-bottom)); left: 1rem; display: flex; flex-direction: column; align-items: center; gap: 0.5rem; pointer-events: none; z-index: 10; } .toast { max-width: 32rem; padding: 0.7rem 1rem; background: var(--text); color: var(--bg); border-radius: var(--radius); box-shadow: 0 4px 16px rgb(0 0 0 / 0.3); } .toast--error { background: var(--danger); color: #fff; }