/* Location: /public_html/assets/css/app.css
 *
 * The whole design system, lifted from the canvas.
 *
 * Three hues carry the brand: cream, ink navy, amber. Sage is semantic and
 * means "community board", never decoration. Amber fills always take ink
 * text, never white, which measures about 7:1.
 *
 * Buttons are always fully rounded. Cards never are. One spring curve for
 * arrivals, one snap curve for touch, and everything stops at
 * prefers-reduced-motion.
 */

/* ===========================================================================
   Tokens
   ======================================================================== */

:root {
  --cream:       #F7F2E9;
  --paper:       #FFFDF7;
  --ink:         #16202B;
  --ink-2:       #1E2935;
  --ink-3:       #26313F;
  --ink-line:    #2E3945;
  --slate:       #44505F;
  --muted:       #6E7887;
  --line:        #E4DBC9;
  --line-2:      #DDD2BC;
  --line-soft:   #EFE7D7;
  --dash:        #CFC3A9;

  --amber:       #C87A1C;
  --amber-deep:  #8E5510;
  --amber-press: #6C3F0A;
  --amber-wash:  #F3E3C6;
  --amber-ink:   #6B5327;
  --amber-dim:   #4A360F;

  --sage:        #4A6F5E;
  --sage-wash:   #E2EAE5;
  --sage-line:   #C6D5CD;
  --sage-ink:    #2C453A;

  --neutral-tint: #E9E3D3;

  /* On dark bands */
  --on-dark:       #F7F2E9;
  --on-dark-2:     #9AA4B1;
  --on-dark-3:     #7F8894;
  --on-dark-link:  #D9D5CC;
  --on-dark-amber: #E6BE85;
  --on-dark-ok:    #86CFAA;
  --on-dark-line:  #38424F;

  --display: 'Gabarito', system-ui, -apple-system, sans-serif;
  --body: 'Hanken Grotesk', system-ui, -apple-system, sans-serif;

  --spring-snappy: linear(0,0.009,0.035 2.1%,0.141 4.4%,0.723 12.9%,0.938 16.7%,
    1.017 19.4%,1.067 22.5%,1.089 26.0%,1.079 30.3%,1.049 36.0%,1.024 42.6%,
    1.011 50.3%,1.004 59.2%,1.001 69.3%,1);
  --ease-snap: cubic-bezier(0.22, 1, 0.36, 1);

  --gutter: 72px;
  --wrap: 1440px;
}

/* ===========================================================================
   Base
   ======================================================================== */

*, *::before, *::after { box-sizing: border-box; }

/* The hidden attribute only sets display:none at the lowest precedence, so any
   element carrying its own display loses to it. Everything here that toggles
   with hidden also carries a layout display, so this has to win. */
[hidden] { display: none !important; }

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  font-family: var(--body);
  font-size: 16px;
  background: var(--cream);
  color: var(--ink);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

a { color: var(--amber-deep); text-decoration: none; }
a:hover { color: var(--amber-press); }

img, svg { max-width: 100%; }
svg { display: block; }

h1, h2, h3, h4 { margin: 0; font-family: var(--display); font-weight: 700; }
p { margin: 0; }

button, input, select, textarea { font: inherit; color: inherit; }

:focus-visible {
  outline: 3px solid var(--amber-deep);
  outline-offset: 2px;
  border-radius: 4px;
}

.sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

.skip-link {
  position: absolute; left: -9999px; top: 0; z-index: 100;
  background: var(--ink); color: var(--on-dark);
  padding: 14px 22px; border-radius: 0 0 14px 0; font-weight: 600;
}
.skip-link:focus { left: 0; color: var(--on-dark); }

/* ===========================================================================
   Typography scale
   ======================================================================== */

.eyebrow {
  font-size: 11.5px; letter-spacing: 0.17em; text-transform: uppercase;
  font-weight: 700; color: var(--amber-deep);
}
.eyebrow--dark { color: var(--on-dark-amber); }
.eyebrow--muted { color: var(--muted); letter-spacing: 0.16em; font-size: 11px; }

.h-hero {
  font-size: clamp(43px, 5.3vw, 76px);
  line-height: 0.98; letter-spacing: -0.042em;
}
.h-section {
  font-size: clamp(30px, 3.4vw, 48px);
  line-height: 1.02; letter-spacing: -0.035em;
}
.h-sub {
  font-size: clamp(26px, 2.6vw, 40px);
  line-height: 1.05; letter-spacing: -0.033em;
}
.h-card {
  font-size: clamp(20px, 1.8vw, 25px);
  line-height: 1.1; letter-spacing: -0.026em;
}
.h-tight { letter-spacing: -0.028em; }

.lede { font-size: 19.5px; line-height: 1.6; color: var(--slate); }
.body { font-size: 17px; line-height: 1.65; color: var(--slate); }
.body-sm { font-size: 15px; line-height: 1.55; color: var(--slate); }
.meta { font-size: 13.5px; color: var(--muted); }
.meta-sm { font-size: 12.5px; color: var(--muted); }

.label {
  display: block; font-size: 11px; letter-spacing: 0.15em;
  text-transform: uppercase; font-weight: 700; color: var(--muted);
}

.figure {
  font-family: var(--display); font-weight: 700; letter-spacing: -0.03em;
  font-variant-numeric: tabular-nums;
}
.figure--xl { font-size: clamp(68px, 9vw, 132px); line-height: 0.86; letter-spacing: -0.055em; font-weight: 800; }
.figure--lg { font-size: 44px; line-height: 1; letter-spacing: -0.04em; }
.figure--md { font-size: 26px; }

.strong-ink { font-style: normal; font-weight: 700; color: var(--ink); }

/* ===========================================================================
   Layout
   ======================================================================== */

.wrap { max-width: var(--wrap); margin: 0 auto; padding: 0 var(--gutter); }

/* Vertical only, deliberately. These were shorthand `padding: 78px 0 80px`,
   and .section is declared after .wrap, so any element carrying both classes
   had its 72px gutter reset to zero and its content ran to the window edge.
   `<section class="wrap section">` is a natural thing to write and appears on
   at least the board page and the homepage, where the band above it kept its
   gutter and the section below it did not. Longhand cannot do that. */
.section { padding-top: 78px; padding-bottom: 80px; }
.section--tight { padding-top: 54px; padding-bottom: 56px; }
.section--flush { padding-top: 0; }

.band--cream { background: var(--cream); color: var(--ink); }
.band--paper { background: var(--paper); color: var(--ink); }
.band--ink   { background: var(--ink); color: var(--on-dark); }
.band--wash  { background: var(--amber-wash); color: var(--ink); }
.band--amber { background: var(--amber); color: var(--ink); }
.band--sage  { background: var(--sage); color: var(--on-dark); }

.band--ink a, .band--sage a { color: var(--on-dark-link); }
.band--ink a:hover, .band--sage a:hover { color: var(--on-dark); }
.band--ink .body, .band--sage .body { color: var(--on-dark-2); }
.band--ink .meta, .band--sage .meta { color: var(--on-dark-2); }

.split {
  display: grid; grid-template-columns: minmax(0, 1fr) 540px;
  gap: 64px; align-items: center;
}
.split--narrow { grid-template-columns: minmax(0, 1fr) 520px; }
.split--left { grid-template-columns: 560px minmax(0, 1fr); }
.split--rail { grid-template-columns: 392px minmax(0, 1fr); gap: 72px; align-items: start; }

.row { display: flex; align-items: center; gap: 16px; }
.row--between { justify-content: space-between; }
.row--end { align-items: flex-end; }
.row--wrap { flex-wrap: wrap; }
.push { margin-left: auto; }
.stack { display: flex; flex-direction: column; gap: 16px; }
.stack--sm { gap: 10px; }
.stack--lg { gap: 26px; }

.grid-3 { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 18px; }
.grid-2 { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 18px; }
.span-2 { grid-column: span 2; }

/* ===========================================================================
   Buttons
   ======================================================================== */

.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 10px;
  height: 52px; padding: 0 26px; border-radius: 999px;
  border: none; background: var(--amber); color: var(--ink);
  font-family: var(--body); font-size: 15.5px; font-weight: 700;
  cursor: pointer; white-space: nowrap; text-align: center;
  transition: transform .35s var(--ease-snap), box-shadow .35s var(--ease-snap),
              background-color .2s var(--ease-snap);
}
.btn:hover { color: var(--ink); transform: translateY(-2px); box-shadow: 0 12px 28px rgba(22,32,43,.18); }
.btn:active { transform: translateY(0) scale(.97); }
.btn[disabled], .btn[aria-disabled="true"] {
  opacity: .5; cursor: not-allowed; transform: none; box-shadow: none;
}

.btn--lg { height: 62px; padding: 0 34px; font-size: 18px; }
.btn--md { height: 58px; font-size: 17px; }
.btn--sm { height: 46px; padding: 0 22px; font-size: 14.5px; font-weight: 600; }
.btn--xs { height: 36px; padding: 0 15px; font-size: 13.5px; font-weight: 600; }
.btn--block { display: flex; width: 100%; }

.btn--ghost {
  background: transparent; border: 1.5px solid var(--ink); color: var(--ink); font-weight: 600;
}
.btn--ghost:hover { background: rgba(22,32,43,.04); }

.btn--dark { background: var(--ink); color: var(--on-dark); font-weight: 600; }
.btn--dark:hover { color: var(--on-dark); }

.btn--board {
  background: var(--sage-wash); border: 1.5px solid var(--sage);
  color: var(--sage-ink); font-weight: 600;
}
.btn--board:hover { color: var(--sage-ink); }

.btn--onink { background: var(--amber); color: var(--ink); }
.btn--onink:hover { color: var(--ink); }

.btn--quiet {
  background: transparent; border: 1px solid var(--on-dark-line);
  color: #E8E3D9; font-weight: 500;
}
.btn--quiet:hover { color: var(--on-dark); background: rgba(255,255,255,.05); }

.btn--icon { width: 44px; height: 44px; padding: 0; flex-shrink: 0; }

/* Tertiary: a text link with a rule under it that wipes away on hover. */
.link-ul { position: relative; display: inline-block; font-weight: 600; color: var(--ink); }
.link-ul:hover { color: var(--ink); }
.link-ul::after {
  content: ''; position: absolute; left: 0; bottom: -3px; height: 1.5px; width: 100%;
  background: currentColor; transform: scaleX(1); transform-origin: left;
  transition: transform .35s var(--ease-snap);
}
.link-ul:hover::after { transform: scaleX(0); transform-origin: right; }

/* Safety net, not the answer. .back-link below is the answer, but .link-ul is
   display:inline-block rather than flex, so a page that puts an icon and a
   word inside one .link-ul anchor gets a block-level svg and the two stack.
   That shipped on the account gift page, the taproom editor, the brewery page,
   the admin brewery editor and the board editor before anybody noticed, which
   is four pages too many for a mistake this easy to make. Flex containers
   blockify their children anyway, so this changes nothing inside .btn, .chip
   or .back-link; it only rescues the one non-flex case. */
.link-ul svg { display: inline-block; vertical-align: -0.16em; }

/* Back links: an arrow and a word, on one line.
   They stack without this. svg is display:block globally, so an icon inside an
   anchor is a block element and breaks the line, dropping the word underneath
   it. .link-ul then draws its rule at width:100% of a box that is now two
   lines tall, so it lands under the arrow rather than under the text. Flex
   puts them back on one row, and the underline goes on the word alone. */
.back-link {
  display: inline-flex; align-items: center; gap: 7px;
  font-size: 13.5px; font-weight: 600; color: var(--muted);
}
.back-link:hover { color: var(--ink); }
.back-link span { text-underline-offset: 3px; }
.back-link:hover span { text-decoration: underline; }

/* On the amber hero band, where --muted is too cool against the wash. */
.band--wash .back-link { color: var(--amber-ink); }
.band--wash .back-link:hover { color: var(--ink); }

/* And on navy, where --muted is #6E7887 against #16202B: about 3.3:1, under
   the 4.5 a 13.5px link needs. --on-dark-2 clears it. */
.band--ink .back-link, .band--sage .back-link { color: var(--on-dark-2); }
.band--ink .back-link:hover, .band--sage .back-link:hover { color: var(--on-dark); }

.link-nav { position: relative; font-size: 15px; font-weight: 500; color: var(--slate); }
.link-nav:hover { color: var(--ink); }
.link-nav::after {
  content: ''; position: absolute; left: 0; bottom: -5px; height: 1.5px; width: 100%;
  background: currentColor; transform: scaleX(0); transform-origin: right;
  transition: transform .35s var(--ease-snap);
}
.link-nav:hover::after { transform: scaleX(1); transform-origin: left; }

.band--ink .link-nav, .band--sage .link-nav { color: var(--on-dark-link); }
.band--ink .link-nav:hover { color: var(--on-dark); }

/* ===========================================================================
   Surfaces
   ======================================================================== */

.card {
  background: var(--paper); border: 1px solid var(--line);
  border-radius: 22px; padding: 26px 28px;
}
.card--lg { border-radius: 26px; padding: 32px 34px; }
.card--sm { border-radius: 16px; padding: 16px 18px; }
.card--flush { padding: 0; overflow: hidden; }
.card--cream { background: var(--cream); }
.card--wash { background: var(--amber-wash); border-color: transparent; }
.card--sage { background: var(--sage-wash); border-color: var(--sage-line); color: var(--sage-ink); }
.card--dark { background: var(--ink-2); border-color: var(--ink-line); color: var(--on-dark); }
.card--dashed { border: 1.5px dashed var(--dash); background: var(--paper); }
.card--selected { border: 2px solid var(--amber); }

.lift {
  transition: transform .35s var(--ease-snap), box-shadow .35s var(--ease-snap),
              border-color .35s var(--ease-snap);
}
.lift:hover { transform: translateY(-4px); box-shadow: 0 16px 36px rgba(22,32,43,.13); }

.rule { height: 1px; background: var(--line); border: 0; margin: 0; }
.rule--soft { background: var(--line-soft); }
.rule--dark { background: var(--ink-line); }

/* ===========================================================================
   Chips, monograms, glyphs
   ======================================================================== */

.chip {
  display: inline-flex; align-items: center; gap: 9px;
  height: 34px; padding: 0 15px; border-radius: 999px;
  background: var(--amber-wash); color: var(--amber-deep);
  font-size: 13px; font-weight: 600; white-space: nowrap;
}
.chip--sage { background: var(--sage-wash); color: var(--sage-ink); }
.chip--ink { background: var(--ink); color: var(--on-dark); }
.chip--amber { background: var(--amber); color: var(--ink); font-weight: 700; }
.chip--outline { background: transparent; border: 1px solid var(--line-2); color: var(--slate); }
.chip--ok { background: var(--sage-wash); color: var(--sage-ink); }
.chip--warn { background: var(--amber-wash); color: var(--amber-ink); }
.chip--off { background: var(--neutral-tint); color: var(--muted); }
.chip--sm { height: 28px; padding: 0 12px; font-size: 12px; }

/* Brewery identity: a two-letter monogram in a tinted rounded square.
   Scales to hundreds of partners with no asset pipeline. */
.monogram {
  display: inline-flex; align-items: center; justify-content: center;
  width: 48px; height: 48px; border-radius: 14px; flex-shrink: 0;
  font-family: var(--display); font-weight: 700; font-size: 18px;
  letter-spacing: -0.02em; background: var(--neutral-tint); color: var(--ink);
}
.monogram--sage { background: var(--sage-wash); color: var(--sage-ink); }
.monogram--amber { background: var(--amber-wash); color: var(--amber-deep); }
.monogram--neutral { background: var(--neutral-tint); color: var(--ink); }
.monogram--sm { width: 38px; height: 38px; border-radius: 11px; font-size: 14px; }
.monogram--lg { width: 88px; height: 88px; border-radius: 24px; font-size: 34px; }
.monogram--xl { width: 148px; height: 148px; border-radius: 36px; font-size: 58px; }

.avatar {
  display: inline-flex; align-items: center; justify-content: center;
  width: 44px; height: 44px; border-radius: 999px; flex-shrink: 0;
  font-family: var(--display); font-weight: 700; font-size: 17px;
  background: var(--ink); color: var(--on-dark);
}
.avatar--amber { background: var(--amber); color: var(--ink); }
.avatar--sage { background: var(--sage); color: var(--on-dark); }

/* The pint glyph: filled amber is available, outlined is spent. */
.pint-grid {
  display: grid; grid-template-columns: repeat(21, minmax(0, 1fr)); gap: 10px 8px;
}
.pint-grid--wide { grid-template-columns: repeat(9, minmax(0, 1fr)); gap: 13px 11px; }
.pint-glyph { display: block; width: 100%; }

.legend { display: flex; gap: 26px; font-size: 14px; font-weight: 600; color: var(--muted); }
.legend span { display: inline-flex; align-items: center; gap: 9px; }
.legend i { width: 13px; height: 13px; border-radius: 4px; display: block; }

/* ===========================================================================
   Forms
   ======================================================================== */

.field { display: block; margin-bottom: 18px; }
.field > .label { margin-bottom: 7px; }

.input, .select, .textarea {
  width: 100%; height: 54px; padding: 0 16px;
  border: 1.5px solid var(--line-2); border-radius: 14px;
  background: var(--paper); color: var(--ink);
  font-size: 16px; font-weight: 500;
  transition: border-color .2s var(--ease-snap), box-shadow .2s var(--ease-snap);
}
.textarea { height: auto; min-height: 120px; padding: 14px 16px; line-height: 1.55; resize: vertical; }
.select { appearance: none; padding-right: 44px;
  background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='20' height='20' viewBox='0 0 24 24' fill='none' stroke='%236E7887' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right 14px center;
}
.input:focus, .select:focus, .textarea:focus {
  outline: none; border-color: var(--amber);
  box-shadow: 0 0 0 3px rgba(200,122,28,.18);
}
.input::placeholder, .textarea::placeholder { color: var(--muted); font-weight: 400; }
.input[aria-invalid="true"], .textarea[aria-invalid="true"] { border-color: #A8332A; }

.field-error { margin-top: 6px; font-size: 13.5px; font-weight: 600; color: #A8332A; }
.field-hint { margin-top: 6px; font-size: 13.5px; color: var(--muted); }

.counter { font-size: 13px; color: var(--muted); font-variant-numeric: tabular-nums; }

/* Radio and checkbox tiles: the whole card is the target, 44px minimum. */
.tile { position: relative; display: block; cursor: pointer; }
.tile input { position: absolute; opacity: 0; width: 0; height: 0; }
/* display:block is load-bearing. These are spans, and an inline box drops
   min-height, refuses to let vertical padding affect line height, and splits
   into fragments around the block-level title inside it. Left inline, the
   border renders in pieces and the tile lies on top of whatever sits above
   and below it. */
.tile-body {
  display: block;
  border: 1.5px solid var(--line); border-radius: 18px; padding: 18px 20px;
  background: var(--paper); min-height: 44px;
  transition: border-color .2s var(--ease-snap), background-color .2s var(--ease-snap),
              transform .35s var(--ease-snap);
}
.tile:hover .tile-body { transform: translateY(-2px); }
.tile input:checked + .tile-body { border: 2px solid var(--amber); padding: 17px 19px; }
.tile input:focus-visible + .tile-body { outline: 3px solid var(--amber-deep); outline-offset: 2px; }
.tile--sage input:checked + .tile-body { border-color: var(--sage); background: var(--sage-wash); }

.switch-row {
  display: flex; align-items: center; gap: 14px;
  padding: 16px 0; border-bottom: 1px solid var(--line-soft);
}
.switch-row:last-child { border-bottom: 0; }

/* A search bar built as one continuous surface, split by hairlines. */
.searchbar {
  background: var(--paper); border-radius: 22px;
  padding: 12px 12px 12px 28px; display: flex; align-items: center;
}
.searchbar .seg { padding: 0 24px; }
.searchbar .seg:first-child { padding-left: 0; flex-grow: 1; min-width: 0; }
.searchbar .divider { width: 1px; height: 48px; background: var(--line); flex-shrink: 0; }
.searchbar input, .searchbar select {
  width: 100%; margin-top: 5px; border: 0; background: transparent;
  font-size: 18px; font-weight: 600; color: var(--ink); outline: none; padding: 0;
  appearance: none;
}
.searchbar select { font-weight: 500; }

/* The searchbar's inputs are not .input, so .input::placeholder never reached
   them and they fell back to the browser default: rgb(117,117,117) inherited
   at font-weight 600. Against a real value in --ink at the same size and the
   same weight, the only difference left was lightness, which is not enough
   when the placeholder is a plausible city. "Somerville, MA" sitting in an
   empty field read as a search that had been run, and the results underneath
   it (every taproom on the platform, because no place was submitted) read as
   a broken radius filter. Same colour as every other placeholder on the site,
   and a lighter weight so it cannot be mistaken for typed text. opacity:1
   because Firefox dims placeholders by default on top of whatever we set. */
.searchbar input::placeholder,
.searchbar select::placeholder { color: var(--muted); font-weight: 400; opacity: 1; }
.searchbar .go {
  width: 64px; height: 64px; border-radius: 18px; background: var(--amber);
  color: var(--ink); display: flex; align-items: center; justify-content: center;
  flex-shrink: 0; border: 0; cursor: pointer;
}

.searchbar--pill {
  border-radius: 999px; padding: 0 8px 0 18px; height: 54px; gap: 10px;
}
.searchbar--pill input { margin-top: 0; font-size: 16px; }
.searchbar--pill .go { width: 44px; height: 44px; border-radius: 999px; }

/* ===========================================================================
   Header and footer
   ======================================================================== */

.site-header {
  height: 80px; display: flex; align-items: center; gap: 36px;
  max-width: var(--wrap); margin: 0 auto; padding: 0 var(--gutter);
}
/* flex-shrink:0 is load-bearing. As a shrinkable flex item the brand gave up
   its width to the nav and the actions long before the 768px breakpoint: at
   1366px the logo rendered 114px instead of 120, at 1024px it was 81px, and
   between 769px and 900px it was zero pixels wide, which is to say gone. The
   page never scrolled sideways, so nothing looked broken; the logo just
   quietly was not there. Only below 360px, where nothing fits at any fixed
   size, is it allowed to give way rather than push the page sideways. */
.brand { display: flex; align-items: center; gap: 10px; color: var(--ink); flex-shrink: 0; }
.brand:hover { color: var(--ink); }
.brand-name {
  font-family: var(--display); font-size: 21px; font-weight: 700; letter-spacing: -0.025em;
}
.site-nav { display: flex; gap: 28px; margin-left: 10px; }
.header-actions { margin-left: auto; display: flex; align-items: center; gap: 22px; }
.nav-toggle { display: none; }

.site-footer { background: var(--ink); color: var(--on-dark); padding: 54px 0 40px; }
.footer-grid {
  display: grid; grid-template-columns: 320px repeat(3, minmax(0, 1fr)); gap: 48px;
}
.footer-col-title {
  font-size: 11.5px; letter-spacing: 0.15em; text-transform: uppercase;
  font-weight: 700; color: var(--on-dark-3);
}
.footer-links {
  margin-top: 16px; display: flex; flex-direction: column; gap: 11px; font-size: 14.5px;
}
.footer-links a { width: max-content; color: var(--on-dark-link); }
.footer-base {
  margin-top: 40px; padding-top: 24px; border-top: 1px solid var(--ink-line);
  display: flex; flex-wrap: wrap; gap: 12px 28px; align-items: center;
  font-size: 12.5px; color: var(--on-dark-3);
}

/* ===========================================================================
   Marquee
   ======================================================================== */

.marquee { overflow: hidden; height: 78px; display: flex; align-items: center; }
.marquee-track { display: flex; width: max-content; animation: marq 38s linear infinite; }
.marquee-track > span {
  display: flex; align-items: center; gap: 44px; padding-right: 44px;
  font-size: 16px; font-weight: 600; color: var(--on-dark-2); white-space: nowrap;
}
.marquee-track .dot { color: var(--amber); }
@keyframes marq { to { transform: translateX(-50%); } }

/* ===========================================================================
   Stat tiles and tables
   ======================================================================== */

.tiles { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 12px; }
.tiles--6 { grid-template-columns: repeat(6, minmax(0, 1fr)); }
.tile-stat { background: var(--cream); border-radius: 14px; padding: 18px; }
.tile-stat--ink { background: var(--ink); color: var(--on-dark); }
.tile-stat--ink .tile-stat-label { color: var(--on-dark-2); }
.tile-stat-label { margin-top: 5px; font-size: 12.5px; color: var(--muted); line-height: 1.35; }

.table { width: 100%; border-collapse: collapse; font-size: 14.5px; }
.table th {
  text-align: left; padding: 12px 14px; font-size: 11px; letter-spacing: 0.14em;
  text-transform: uppercase; color: var(--muted); font-weight: 700;
  border-bottom: 1px solid var(--line);
}
.table td { padding: 14px; border-bottom: 1px solid var(--line-soft); vertical-align: middle; }
.table tr:last-child td { border-bottom: 0; }
.table .num { text-align: right; font-variant-numeric: tabular-nums; font-weight: 700; }
.table--dark th { color: var(--on-dark-3); border-bottom-color: var(--ink-line); }
.table--dark td { border-bottom-color: var(--ink-line); }

.bars { display: flex; align-items: flex-end; gap: 10px; height: 160px; }
.bar { flex: 1; background: var(--amber); border-radius: 8px 8px 0 0; position: relative; min-height: 3px; }
.bar--muted { background: var(--line-2); }
.bar-label {
  position: absolute; bottom: -22px; left: 0; right: 0; text-align: center;
  font-size: 11.5px; color: var(--muted);
}

.empty {
  border: 1.5px dashed var(--dash); border-radius: 20px;
  padding: 44px 32px; text-align: center; color: var(--muted);
}

/* ===========================================================================
   Flash messages
   ======================================================================== */

/* Toasts, bottom right. They never push content down and they never stay.
   No JS: one animation carries the whole life of the toast, holds it for about
   four and a half seconds, then fades and sets visibility:hidden, which also
   takes it out of hit testing so a spent toast cannot swallow a click.
   Hovering pauses it, so a long message can be read. */
.flashes {
  position: fixed; z-index: 60;
  right: 20px; bottom: 20px; left: auto; top: auto;
  width: min(390px, calc(100vw - 40px));
  max-width: none; margin: 0; padding: 0;
  display: flex; flex-direction: column; gap: 10px;
  pointer-events: none;
}
.flash {
  pointer-events: auto;
  display: flex; align-items: flex-start; gap: 12px;
  border-radius: 16px; padding: 15px 18px; margin-bottom: 0;
  font-size: 15px; font-weight: 500;
  box-shadow: 0 14px 34px rgba(22,32,43,.16), 0 2px 6px rgba(22,32,43,.08);
  animation: toast 5s var(--ease-snap) forwards;
}
.flash:hover { animation-play-state: paused; }
.flash--ok { background: var(--sage-wash); color: var(--sage-ink); }
.flash--error { background: #F7E3E0; color: #7A241C; }
.flash--info { background: var(--amber-wash); color: var(--amber-ink); }

@keyframes toast {
  0%   { opacity: 0; transform: translateY(14px) scale(.97); }
  7%   { opacity: 1; transform: translateY(0) scale(1); }
  90%  { opacity: 1; transform: translateY(0) scale(1); }
  100% { opacity: 0; transform: translateY(6px) scale(.99); visibility: hidden; }
}
/* Reduced motion still has to end in hidden, or the toast would sit there
   for good. Cut, do not slide. */
@keyframes toast-cut {
  0%, 99% { opacity: 1; visibility: visible; }
  100%    { opacity: 0; visibility: hidden; }
}

/* ===========================================================================
   Portal shell: dashboard, admin, account
   ======================================================================== */

.portal { display: grid; grid-template-columns: 268px minmax(0, 1fr); min-height: 100vh; }
.portal-side {
  background: var(--ink); color: var(--on-dark); padding: 28px 20px;
  display: flex; flex-direction: column; gap: 26px;
}
.portal-main { padding: 36px 40px 64px; min-width: 0; }
.portal-head { display: flex; align-items: flex-end; justify-content: space-between; gap: 24px; margin-bottom: 26px; }

.side-nav { display: flex; flex-direction: column; gap: 4px; }
.side-nav a {
  display: flex; align-items: center; gap: 12px; height: 46px; padding: 0 16px;
  border-radius: 999px; color: var(--on-dark-link); font-size: 15px; font-weight: 500;
  transition: background-color .2s var(--ease-snap), color .2s var(--ease-snap);
}
.side-nav a:hover { background: var(--ink-3); color: var(--on-dark); }
.side-nav a.is-active { background: var(--amber); color: var(--ink); font-weight: 700; }
.side-foot { margin-top: auto; font-size: 13px; color: var(--on-dark-3); }

.org-switch {
  background: var(--ink-2); border: 1px solid var(--ink-line);
  border-radius: 16px; padding: 14px 16px;
}

/* ===========================================================================
   Mobile flow shell: the five send steps, the recipient screens
   ======================================================================== */

.flow { max-width: 430px; margin: 0 auto; padding: 0 20px 40px; min-height: 100vh; }
.flow-head { height: 58px; display: flex; align-items: center; gap: 14px; }
.flow-back { width: 44px; height: 44px; margin-left: -12px; display: flex; align-items: center; justify-content: center; color: var(--slate); }

.pips { display: flex; gap: 6px; flex-grow: 1; }
.pip { height: 4px; flex: 1; border-radius: 999px; background: var(--line); }
.pip.is-done { background: var(--amber-deep); }
.pip.is-current { background: var(--amber); }

.flow-footer {
  position: sticky; bottom: 0; background: var(--cream);
  padding: 16px 0 calc(20px + env(safe-area-inset-bottom, 0px));
  margin-top: 24px;
  border-top: 1px solid var(--line);
}

/* ===========================================================================
   The live credential
   ======================================================================== */

.credential {
  min-height: 100vh; background: var(--amber); color: var(--ink);
  display: flex; flex-direction: column; padding: 20px;
}
.credential.is-expired .cred-live { display: none; }

.cred-code {
  font-family: var(--display); font-weight: 800;
  font-size: clamp(54px, 17vw, 86px); letter-spacing: 0.02em;
  line-height: 1; text-align: center; font-variant-numeric: tabular-nums;
}
.cred-qr {
  width: min(280px, 72vw); aspect-ratio: 1; margin: 0 auto;
  background: var(--paper); border-radius: 20px; padding: 14px;
}
.cred-qr svg { width: 100%; height: 100%; }

.cred-clock {
  font-variant-numeric: tabular-nums; font-weight: 700; font-size: 17px;
}
.cred-ring {
  height: 6px; border-radius: 999px; background: rgba(22,32,43,.18); overflow: hidden;
}
.cred-ring::after {
  content: ''; display: block; height: 100%; border-radius: 999px;
  background: var(--ink); transform: scaleX(var(--progress, 1)); transform-origin: left;
  transition: transform .3s linear;
}

/* ===========================================================================
   Staff redemption app
   ======================================================================== */

.staff { min-height: 100vh; background: var(--ink); color: var(--on-dark); padding-bottom: 92px; }
.staff-bar {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 20;
  background: var(--ink-2); border-top: 1px solid var(--ink-line);
  display: flex; padding: 8px;
}
.staff-bar a {
  flex: 1; display: flex; flex-direction: column; align-items: center; gap: 4px;
  padding: 10px 4px; border-radius: 14px; font-size: 12px; font-weight: 600;
  color: var(--on-dark-2);
}
.staff-bar a.is-active { background: var(--ink-3); color: var(--on-dark); }

.code-input {
  width: 100%; height: 76px; text-align: center; letter-spacing: 0.22em;
  font-family: var(--display); font-size: 38px; font-weight: 700;
  text-transform: uppercase; border-radius: 18px;
  border: 1.5px solid var(--ink-line); background: var(--ink-2); color: var(--on-dark);
}
.code-input::placeholder { color: #4C5765; letter-spacing: 0.22em; }

.scan-frame {
  position: relative; border-radius: 22px; overflow: hidden;
  background: #0F171F; aspect-ratio: 1; max-width: 420px; margin: 0 auto;
}
.scan-frame video { width: 100%; height: 100%; object-fit: cover; }

.result-ok { background: var(--sage); color: #fff; }
.result-bad { background: #8C2F24; color: #fff; }

/* ===========================================================================
   Motion
   ======================================================================== */

@keyframes rise {
  from { opacity: 0; transform: translateY(22px); filter: blur(6px); }
  to   { opacity: 1; transform: translateY(0); filter: blur(0); }
}
@keyframes pop {
  from { opacity: 0; transform: scale(.92); }
  to   { opacity: 1; transform: scale(1); }
}

.r { animation: rise .6s var(--spring-snappy) both; }
.pop { animation: pop .6s var(--spring-snappy) both; }
.d1 { animation-delay: .08s } .d2 { animation-delay: .16s } .d3 { animation-delay: .24s }
.d4 { animation-delay: .32s } .d5 { animation-delay: .4s }  .d6 { animation-delay: .48s }

@media (prefers-reduced-motion: reduce) {
  .r, .pop { animation: none; }
  .marquee-track { animation: none; }
  .lift:hover, .btn:hover, .tile:hover .tile-body { transform: none; }
  .flash { animation: toast-cut 5s linear forwards; }
  * { scroll-behavior: auto !important; }
}

/* ===========================================================================
   Responsive. One breakpoint, as designed: every multi-column grid collapses.
   ======================================================================== */

/* The header runs out of room before anything else does, because the nav and
   the action links cannot shrink and the logo is no longer allowed to. It
   collapses to the hamburger at 1000px rather than waiting for 768, which is
   where the rest of the layout goes single column. */
@media (max-width: 1000px) {
  .site-nav, .header-actions .link-nav { display: none; }
  .nav-toggle { display: flex; margin-left: auto; }
}

@media (max-width: 768px) {
  /* 20px was the spec, and on a 390px screen it reads as the content being
     pressed against the bezel: cards land 20px from the edge while their own
     padding pushes the text in another 18, so the card looks squeezed and the
     page looks tight. 24 costs 8px of content width and buys a margin that
     looks deliberate. */
  :root { --gutter: 24px; }

  .section { padding: 34px 0 36px; }
  .section--tight { padding: 28px 0 30px; }

  .split, .split--narrow, .split--left, .split--rail,
  .grid-3, .grid-2, .tiles, .tiles--6, .footer-grid {
    grid-template-columns: minmax(0, 1fr);
    gap: 22px;
  }
  .span-2 { grid-column: auto; }

  /* The hero splits with the concept object under the copy. */
  .split > * { min-width: 0; }

  .site-header { height: 66px; gap: 12px; }
  .header-actions { gap: 10px; }

  .searchbar { flex-direction: column; align-items: stretch; padding: 16px; border-radius: 20px; }
  .searchbar .seg { padding: 12px 0; }
  .searchbar .divider { width: 100%; height: 1px; }
  .searchbar .go { width: 100%; height: 54px; border-radius: 14px; }

  /* The pill is one field and stays a row. The rules above are for the
     three-segment bar on /find, which genuinely has to stack, but
     .searchbar--pill matches .searchbar too and inherited all of it: on
     /send step 1 the magnifier, the input and the button stacked to about
     150px of content inside a box still pinned to height:54px, so all three
     spilled out below their own border and the button ran the full width
     across the results heading underneath. */
  .searchbar--pill {
    flex-direction: row; align-items: center;
    padding: 0 8px 0 14px; border-radius: 999px;
  }
  .searchbar--pill .go { width: 44px; height: 44px; border-radius: 999px; }

  .portal { grid-template-columns: minmax(0, 1fr); }
  .portal-main { padding: 22px 20px 96px; }
  /* The dashboard sidebar becomes a bottom bar. */
  .portal-side {
    position: fixed; left: 0; right: 0; bottom: 0; top: auto; z-index: 30;
    flex-direction: row; align-items: center; gap: 8px; padding: 8px;
    border-top: 1px solid var(--ink-line);
  }
  .portal-side .side-brand, .portal-side .org-switch, .portal-side .side-foot { display: none; }
  .side-nav { flex-direction: row; width: 100%; gap: 4px; }
  .side-nav a {
    flex: 1; justify-content: center; height: 52px; padding: 0 6px;
    font-size: 11.5px; flex-direction: column; gap: 3px; border-radius: 14px;
  }
  .side-nav a span { display: none; }
  .side-nav a small { display: block; }

  .pint-grid { grid-template-columns: repeat(12, minmax(0, 1fr)); gap: 7px 6px; }
  .pint-grid--wide { grid-template-columns: repeat(7, minmax(0, 1fr)); }

  /* Clear of the portal bottom bar and the staff app bar, both fixed to the
     bottom edge on mobile. Slightly high on public pages, which is the right
     trade against a toast hiding behind a nav bar. One number to change. */
  .flashes { right: 12px; left: 12px; bottom: 88px; width: auto; }

  .marquee { height: 62px; }
  .legend { flex-direction: column; gap: 10px; }
  .portal-head { flex-direction: column; align-items: flex-start; gap: 14px; }
}

@media (max-width: 360px) {
  /* Nothing fits here at a fixed size. A squashed mark beats a page that
     scrolls sideways, and this is the only width where that trade applies. */
  .brand { flex-shrink: 1; }
}

@media (max-width: 420px) {
  .cred-code { font-size: 15vw; }
}

/* Print: a board or a receipt occasionally gets printed behind the bar. */
@media print {
  .site-header, .site-footer, .staff-bar, .flow-footer, .btn { display: none !important; }
  body { background: #fff; }
  .card { break-inside: avoid; }
}