/*
 * The venue portal, on top of styles.css. Every colour and space is a
 * variable from the shared sheet. Short lines, few of them: a bar manager
 * reads this on a phone between customers.
 */

/*
 * The portal takes the app's look (Jordan, 2026-10-25). The public pages keep
 * their own palette, so the app's values are set here, on the portal's body,
 * copied from colorDark and radius in src/theme/tokens.ts.
 */
.portal {
  --void: #141414;
  --abyss: #1e1e1e;
  --card: #2e2e2e;
  --surface: #3b3b3b;
  --raised: #494949;
  --control-border: #7f7f7f;
  --text-hero: #efefef;
  --text-primary: #c7c7c7;
  --text-secondary: #919191;
  --amber-500: #ffa737;
  --on-accent: #141414;
  --radius-button: 4px;
  --radius-card: 6px;
  --radius-chip: 4px;
}

/* The app's buttons: uppercase, tracked, dark text on amber. */
.portal .button {
  color: var(--on-accent);
  font-size: var(--text-body);
  font-weight: 700;
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
}

.portal .button--outline {
  color: var(--amber-500);
}

.nav__group {
  display: flex;
  align-items: center;
  gap: var(--space-base);
}

.nav__button {
  background: none;
  border: 0;
  padding: 0;
  font: inherit;
  cursor: pointer;
}

/* .nav__link sets a display of its own, which would beat the hidden attribute. */
.nav__button[hidden] {
  display: none;
}

.portal-head {
  padding-block: var(--space-lg) var(--space-base);
}

.portal-head .ask {
  margin-bottom: var(--space-xs);
}

.portal-line {
  margin: 0;
  font-size: var(--text-body-lg);
}

.portal-line--quiet {
  color: var(--text-secondary);
  font-size: var(--text-body);
}

.portal-kicker {
  margin: 0 0 var(--space-sm);
  font-size: var(--text-caption);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  color: var(--amber-500);
}

.portal-card {
  background: var(--card);
  border: 1px solid transparent;
  border-radius: var(--radius-card);
  padding: var(--space-lg);
  margin-block: var(--space-base);
}

.portal-card--rules {
  border-color: var(--amber-500);
}

.portal-title {
  margin: 0 0 var(--space-md);
  font-size: var(--text-title);
  line-height: var(--leading-tight);
}

.portal-rules,
.portal-hours {
  margin: 0;
  padding: 0;
  list-style: none;
}

.portal-rules li {
  padding-block: var(--space-sm);
  border-top: 1px solid var(--control-border);
  font-size: var(--text-body-lg);
}

.portal-rules li:first-child {
  border-top: 0;
}

.portal-hours li {
  display: flex;
  justify-content: space-between;
  gap: var(--space-base);
  padding-block: var(--space-sm);
  border-top: 1px solid var(--control-border);
  font-size: var(--text-body-lg);
}

.portal-hours li:first-child {
  border-top: 0;
}

.portal-hours li span:first-child {
  font-weight: 600;
}

.portal-hours li span:last-child {
  text-align: right;
}

.portal-hours li.is-closed span:last-child {
  color: var(--text-secondary);
}

.portal-card__head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-base);
}

.portal-card__head .portal-title {
  margin-bottom: var(--space-md);
}

.link-action[type='button'] {
  background: none;
  border: 0;
  padding: 0;
  font: inherit;
  cursor: pointer;
}

/* Forms: one row per day, or one field per line. */
.portal-form {
  margin-top: var(--space-md);
}

.portal-row {
  display: grid;
  grid-template-columns: 2.6rem auto 1fr auto 1fr;
  align-items: center;
  gap: var(--space-sm);
  padding-block: var(--space-xs);
  font-size: var(--text-body);
}

.portal-row__day {
  font-weight: 600;
}

.portal-row__to {
  color: var(--text-secondary);
}

.input--time {
  min-height: 0;
  padding: var(--space-sm);
}

.portal-form__actions {
  display: flex;
  gap: var(--space-sm);
  margin-top: var(--space-md);
}

.portal-form .form-error {
  margin-top: var(--space-sm);
}

/* Offers: one block each, with its state. */
.portal-offer {
  padding-block: var(--space-md);
  border-top: 1px solid var(--control-border);
}

.portal-offer:first-child {
  border-top: 0;
}

.portal-offer__head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-sm);
}

.portal-offer__title {
  margin: 0;
  font-size: var(--text-body-lg);
  font-weight: 600;
}

.portal-offer__meta,
.portal-offer__body {
  margin: var(--space-xs) 0 0;
  color: var(--text-secondary);
  font-size: var(--text-body);
}

.portal-offer__actions {
  display: flex;
  gap: var(--space-base);
  margin-top: var(--space-sm);
}

.pill {
  display: inline-block;
  padding: 0.1rem var(--space-sm);
  border-radius: var(--radius-chip);
  font-size: var(--text-caption);
  font-weight: 600;
  white-space: nowrap;
  border: 1px solid var(--control-border);
  color: var(--text-secondary);
}

.pill--live {
  border-color: var(--success);
  color: var(--success);
}

.pill--pending {
  border-color: var(--amber-500);
  color: var(--amber-300);
}

/* The code stands apart: amber edge, raised fill, everything centred. */
.portal-code-card {
  background: var(--raised);
  border: 2px solid var(--amber-500);
  border-radius: var(--radius-card);
  padding: var(--space-lg);
  margin-block: var(--space-base);
  text-align: center;
}

.portal-code-lead {
  margin: 0 0 var(--space-sm);
  font-size: var(--text-body-lg);
}

.portal-code {
  margin: var(--space-sm) 0 var(--space-xs);
  font-size: var(--text-hero-size);
  font-weight: 700;
  letter-spacing: 0.08em;
  font-variant-numeric: tabular-nums;
}

/* A scanner needs dark modules on light with a quiet zone around them. */
.portal-qr {
  display: inline-block;
  margin: 0 auto var(--space-sm);
  padding: var(--space-sm);
  border-radius: var(--radius-sm);
  background: #ffffff;
  width: min(60vw, 240px);
}

.portal-qr svg {
  display: block;
  width: 100%;
  height: auto;
}

/* ---------------------------------------------------------------------------
 * Your Tipple: the panel that gives something back. Dense on purpose — a bar
 * manager reads it standing up, and four figures on one line beat four cards.
 * ------------------------------------------------------------------------- */

.stats-window {
  font-size: var(--text-caption);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  color: var(--text-secondary);
  white-space: nowrap;
}

.stats-figures {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: var(--space-sm);
  margin: 0 0 var(--space-md);
  padding: 0;
  list-style: none;
}

/* Four across is tight but legible at 320px; the labels wrap, the figures do not. */
.stats-figure__value {
  display: block;
  font-size: var(--text-heading);
  font-weight: 700;
  line-height: var(--leading-tight);
  font-variant-numeric: tabular-nums;
  color: var(--amber-500);
}

.stats-figure__label {
  display: block;
  margin-top: var(--space-xs);
  font-size: var(--text-caption);
  line-height: var(--leading-normal);
  color: var(--text-secondary);
}

/* One column per day of the window. Heights are set in the script. */
.stats-strip {
  display: flex;
  align-items: flex-end;
  gap: 2px;
  height: 72px;
  margin-top: var(--space-base);
}

.stats-bar {
  flex: 1 1 0;
  min-height: 2px;
  border-radius: 1px;
  background: var(--surface);
}

.stats-bar--has {
  background: var(--amber-500);
}

.stats-axis {
  display: flex;
  justify-content: space-between;
  margin: var(--space-xs) 0 0;
  font-size: var(--text-micro);
  color: var(--text-secondary);
}

.stats-offers {
  margin: var(--space-base) 0 0;
  padding: 0;
  list-style: none;
}

.stats-offer {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-base);
  padding-block: var(--space-sm);
  border-top: 1px solid var(--control-border);
}

.stats-offer__title {
  font-size: var(--text-body);
}

.stats-offer__tier {
  margin-left: var(--space-xs);
  font-size: var(--text-micro);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  color: var(--amber-300);
}

.stats-offer__count {
  font-size: var(--text-body);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
  color: var(--text-secondary);
}

@media (max-width: 380px) {
  .stats-figures {
    grid-template-columns: repeat(2, 1fr);
    gap: var(--space-md);
  }
}

/* ---------------------------------------------------------------------------
 * Tabs: one page at a time. A bar opens the portal to check a number or fix a
 * time, not to read six cards. Tabs share the row's width equally; one too
 * long for its share takes its own width, and the row scrolls sideways on a
 * narrow phone rather than wrapping, so the page below it never moves.
 * ------------------------------------------------------------------------- */

.portal-tabs {
  display: flex;
  border-bottom: 1px solid var(--surface);
  margin-block: var(--space-base);
  overflow-x: auto;
  scrollbar-width: none;
}

.portal-tabs::-webkit-scrollbar {
  display: none;
}

.portal-tab {
  flex: 1 1 0;
  min-width: max-content;
  min-height: var(--touch-target);
  padding: 0 var(--space-sm);
  background: none;
  border: 0;
  border-radius: var(--radius-chip) var(--radius-chip) 0 0;
  font: inherit;
  font-size: var(--text-body);
  color: var(--text-secondary);
  white-space: nowrap;
  cursor: pointer;
}

.portal-tab.is-on {
  background: var(--amber-500);
  color: var(--on-accent);
  font-weight: 600;
}

/* All five fit a 360px phone at caption size. */
@media (max-width: 480px) {
  .portal-tab {
    padding: 0 var(--space-xs);
    font-size: var(--text-caption);
  }
}

.portal-tab:focus-visible {
  outline: 2px solid var(--amber-300);
  outline-offset: 2px;
}

/* The first card in a panel sits against the tabs; the rule is the separator. */
.portal-panel > .portal-card:first-child,
.portal-panel > .portal-code-card:first-child {
  margin-top: 0;
}

/* ---------------------------------------------------------------------------
 * Happy hours as a ladder: a day, then as many hours as the bar runs, each
 * with what it costs. Five rows a day is normal here, so the rows are tight.
 * ------------------------------------------------------------------------- */

.happy-day {
  padding-block: var(--space-sm);
  border-top: 1px solid var(--control-border);
}

.happy-day__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-base);
  min-height: var(--touch-target);
}

/* Wrapping rather than a breakpoint: the two times stay on one line as long as
   they fit, and the price drops below them when they do not. A media query
   would have to guess at the width of a time control, which differs by
   browser and by platform. */
.happy-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-sm);
  padding-block: var(--space-xs);
}

/* `.input` is width:100%, which in a flex row makes every control its own
   line. A basis narrow enough for two times plus the word between them keeps
   a span on one line at 375px, which is the width this is edited at. */
.happy-row .input--time {
  flex: 0 1 7.5rem;
  width: auto;
  min-width: 0;
  padding-inline: var(--space-sm);
}

.input--price {
  flex: 1 1 7rem;
  min-width: 7rem;
}

/* A price list row: the item takes the room, the price keeps a fixed width. */
.price-row {
  display: flex;
  align-items: center;
  gap: var(--space-sm);
  padding-block: var(--space-xs);
}

.price-row .input--item {
  flex: 1 1 auto;
  width: auto;
  min-width: 0;
}

.price-row .input--amount {
  flex: 0 0 6rem;
  width: 6rem;
}

/* ---------------------------------------------------------------------------
 * Add a venue: the Tipple view. Chips wrap, the rest is the same form the
 * rest of the portal uses.
 * ------------------------------------------------------------------------- */

.add-types {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-sm);
}

.add-chip {
  display: flex;
  align-items: center;
  gap: var(--space-xs);
  min-height: var(--touch-target);
  padding: 0 var(--space-md);
  border: 1px solid var(--control-border);
  border-radius: var(--radius-chip);
  font-size: var(--text-body);
  cursor: pointer;
}

.add-chip:has(input:checked) {
  background: var(--amber-500);
  border-color: var(--amber-500);
  color: var(--on-accent);
}

/* The queue's right-hand side carries a count and a button, not just a count. */
#queue .stats-offer__count {
  display: flex;
  align-items: baseline;
  gap: var(--space-md);
}

#add-form textarea.input {
  resize: vertical;
}

/* Applications: each row is a .portal-offer, so the list itself is bare. */
.portal-applications {
  margin: 0;
  padding: 0;
  list-style: none;
}

/* Your listing: the photo pickers. The preview shows what was chosen. */
.listing-image {
  display: grid;
  gap: var(--space-sm);
  margin-bottom: var(--space-base);
}

.listing-image__preview {
  display: block;
  width: 100%;
  aspect-ratio: 16 / 9;
  object-fit: cover;
  border-radius: var(--radius-card, var(--radius-sm));
  background: var(--surface);
}

.listing-image__preview.is-square {
  width: 96px;
  aspect-ratio: 1;
}

.listing-image__file {
  min-height: var(--touch-target);
  color: var(--text-primary);
  font: inherit;
  font-size: var(--text-body);
}

#listing-form .portal-title {
  margin-top: var(--space-lg);
}

#listing-form .portal-title:first-child {
  margin-top: 0;
}

/* `display: block` above would otherwise beat the hidden attribute. */
.listing-image__preview[hidden] {
  display: none;
}

/* The line under an autofill button, kept clear of the next field's label. */
.listing-note {
  margin: var(--space-xs) 0 var(--space-base);
}

/* Row actions keep each label on one line and wrap as whole buttons. */
.portal-offer__actions {
  flex-wrap: wrap;
}

.portal-offer__actions .link-action {
  white-space: nowrap;
}
