/* ============================================================
   studio.css — shared shell for the two event sub-pages
   (checkin.html · nametag.html)

   Tokens mirror assets/css/styles.css so the tools sit inside the
   same visual system as the landing page. Kept in a separate file
   because the landing sheet is 860 lines the tools never touch.
   ============================================================ */

:root{
  /* Without this, Chrome's "Auto Dark Mode for Web Contents" rewrites the
     palette on a dark-themed OS: the sand tag turns black, the teal glow
     blows up, and the navy text stays navy — unreadable, and it bakes
     straight into the printed PDF. The tag is a light artefact by design. */
  color-scheme: light;

  --ink:          #12222F;
  --navy:         #0B1B27;
  --navy-mid:     #0E2233;
  --sand:         #F6F0E6;
  --clay:         #EDE3D2;
  --cream:        #FFFCF6;

  --cyan-deep:    #0E6E86;
  --cyan-dark:    #0B4A5C;
  --amber:        #F2B24C;
  --amber-ink:    #231605;
  --brown:        #7A5A32;
  --rust:         #8A3A2A;

  --muted:        #5A6B76;
  --muted-2:      #4A5C68;
  --line-field:   rgba(18, 34, 47, 0.25);

  --font-display: 'Bricolage Grotesque', 'Segoe UI', sans-serif;
  --font-body:    'Be Vietnam Pro', 'Segoe UI', sans-serif;

  --radius:       14px;

  /* ── Kích thước thẻ tên ──────────────────────────────────
     The tag is drawn on a --tag-cols x --tag-rows unit grid; every inner
     dimension is a multiple of --u, so these values drive the printed card,
     the sheet layout and the preview alike.

       93mm / 348 cols          = 0.267241mm per unit
       497.677 rows x 0.267241  = 133mm tall

     --tag-rows is what fixes the aspect ratio: cols x height / width,
     i.e. 348 x 133 / 93. Recompute it if the proportions change.
     ──────────────────────────────────────────────────────── */
  --tag-cols:   348;
  --tag-rows:   497.677;
  --tag-width:  93mm;
  --u-print:    calc(var(--tag-width) / var(--tag-cols));

  /* Half of A4's 297mm height — where the finished sheet gets cut in two. */
  --a5-half:     148.5mm;

  /* 93mm cards leave much less room than 84mm ones: two across plus a 10mm
     gutter is 196mm of A4's 210mm, and the two rows span 7.75mm to 289.25mm
     down the page. A 6mm margin clears both, and still stays outside the
     ~5mm strip most laser printers cannot reach. */
  --page-margin: 6mm;
}

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

/* .btn sets display, which would otherwise beat the UA [hidden] rule and
   leave JS-hidden buttons on screen. */
[hidden] { display: none !important; }

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

body{
  margin: 0;
  background: var(--clay);
  font-family: var(--font-body);
  color: var(--ink);
  font-size: 16px;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
}

a { color: var(--cyan-deep); text-decoration: none; }
a:hover { color: var(--navy); }

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

img { max-width: 100%; }

.skip-link{
  position: absolute; left: -9999px; top: 0; z-index: 99;
  background: var(--navy); color: #fff; padding: 12px 18px; border-radius: 0 0 8px 0;
}
.skip-link:focus { left: 0; color: #fff; }

:where(a, button, input, select, textarea, label[role="button"]):focus-visible{
  outline: 3px solid var(--cyan-deep);
  outline-offset: 2px;
}

/* ── Page chrome ─────────────────────────────────────────── */

.studio-bar{
  display: flex; flex-wrap: wrap; align-items: center; gap: 14px 22px;
  padding: 16px 5vw;
  background: var(--navy);
  color: rgba(240, 247, 250, 0.86);
}
.studio-bar__brand{
  display: inline-flex; align-items: center; gap: 12px;
  font-family: var(--font-display); font-weight: 800; letter-spacing: .04em;
  color: #fff;
}
.studio-bar__brand:hover { color: #fff; }
.studio-bar__accent { color: #48CFEB; }
.studio-bar__rule { width: 1px; height: 18px; background: rgba(255,255,255,.3); }
.studio-bar__venue { font-family: var(--font-display); font-weight: 600; font-size: 15px; color: var(--amber); }
.studio-bar__nav { display: flex; flex-wrap: wrap; gap: 8px; margin-left: auto; }
.studio-bar__nav a{
  padding: 8px 15px; border-radius: 100px; font-size: 14.5px; font-weight: 600;
  color: rgba(240, 247, 250, 0.86); border: 1px solid rgba(255,255,255,.2);
}
.studio-bar__nav a:hover { color: #fff; border-color: rgba(255,255,255,.5); }
.studio-bar__nav a[aria-current="page"]{
  background: #fff; color: var(--navy); border-color: #fff;
}

.page{
  min-height: 100vh;
  padding: 40px 5vw 72px;
  display: flex; flex-direction: column; gap: 32px;
}

.page-head{
  display: flex; flex-wrap: wrap; align-items: flex-end; justify-content: space-between;
  gap: 24px;
}
.page-head__text { display: flex; flex-direction: column; gap: 10px; }
.eyebrow{
  font-size: 13px; letter-spacing: .26em; text-transform: uppercase;
  color: var(--cyan-deep); font-weight: 700;
}
.page-title{
  margin: 0;
  font-family: var(--font-display); font-weight: 800;
  font-size: clamp(28px, 4.4vw, 40px); line-height: 1.05;
}
.page-lede { margin: 0; font-size: 16px; color: var(--muted-2); max-width: 64ch; }

/* ── Two-column workbench ───────────────────────────────── */

.workbench{
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: 40px;
  align-items: start;
}
.workbench__controls { display: flex; flex-direction: column; gap: 26px; min-width: 0; }
.workbench__preview{
  display: flex; flex-direction: column; gap: 16px; align-items: center;
  position: sticky; top: 24px;
}
.preview-label{
  font-size: 13px; letter-spacing: .22em; text-transform: uppercase;
  color: var(--brown); font-weight: 700;
}
/* The preview renders at true physical size. On phones even that is wider
   than the gutter allows, so it shrinks its unit to fit. */
.workbench__preview .tag{
  --u: min(var(--u-print), calc((100vw - 44px) / var(--tag-cols)));
}

@media (max-width: 980px){
  .workbench { grid-template-columns: minmax(0, 1fr); }
  .workbench__preview { position: static; order: -1; }
}

/* ── Panels ─────────────────────────────────────────────── */

.panel{
  background: var(--sand);
  border-radius: var(--radius);
  padding: 30px 28px;
  display: flex; flex-direction: column; gap: 20px;
}
.panel__title{
  margin: 0;
  font-family: var(--font-display); font-weight: 700; font-size: 22px;
}
.panel__head{
  display: flex; align-items: baseline; justify-content: space-between; gap: 20px;
}
.panel__hint { margin: 0; font-size: 15px; line-height: 1.6; color: var(--muted); }

.field { display: flex; flex-direction: column; gap: 8px; }
.field__label { font-size: 15px; font-weight: 600; }
.field__hint { font-weight: 400; color: var(--muted); }
.field__input{
  border: 1px solid var(--line-field); border-radius: 8px;
  padding: 14px 16px; font-size: 17px;
  background: var(--cream); color: var(--ink);
}
.field__input::placeholder { color: rgba(18, 34, 47, .42); }

.field__input--narrow { max-width: 160px; }

.field__colour{
  width: 84px; height: 44px; padding: 4px;
  border: 1px solid var(--line-field); border-radius: 8px;
  background: var(--cream); cursor: pointer;
}

.toggle { display: inline-flex; align-items: center; gap: 8px; font-size: 15px; font-weight: 600; cursor: pointer; }
.toggle input { width: 18px; height: 18px; accent-color: var(--cyan-deep); cursor: pointer; }

code{
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: .92em; background: rgba(18, 34, 47, .07);
  padding: 1px 5px; border-radius: 4px;
}

#kraft-ink-controls { display: flex; flex-direction: column; gap: 20px; }

/* The cut guide across the middle of the A4. Absolute so it never takes a
   grid cell, and so it still lands at the halfway mark when only the top
   row of tags is being printed and the sheet box is half height. */
.sheet { position: relative; }
.sheet__cut { position: absolute; }

.field-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; }
@media (max-width: 560px){ .field-grid { grid-template-columns: 1fr; } }

.slider { width: 100%; accent-color: var(--cyan-deep); }

.row { display: flex; flex-wrap: wrap; gap: 16px; align-items: center; }

.dropzone{
  display: flex; flex-direction: column; gap: 12px;
  border: 1.5px dashed var(--line-field); border-radius: 10px;
  padding: 18px;
  background: rgba(255, 252, 246, .55);
  transition: border-color .15s ease, background-color .15s ease;
}
.dropzone.is-over { border-color: var(--cyan-deep); background: rgba(14, 110, 134, .1); }

/* ── Buttons ────────────────────────────────────────────── */

/* inline-block, not flex: these labels contain inline <span> counters and a
   flex gap would open a visible hole mid-sentence. */
.btn{
  border: none; border-radius: 8px;
  padding: 15px 24px; font-size: 16px; font-weight: 700;
  cursor: pointer; display: inline-block; text-align: center;
}
.btn:disabled { opacity: .45; cursor: not-allowed; }
.btn--ink   { background: var(--navy-mid); color: #fff; padding: 16px 26px; }
.btn--ink:hover:not(:disabled) { background: var(--navy); }
.btn--teal  { background: var(--cyan-deep); color: #fff; font-weight: 600; padding: 14px 22px; }
.btn--teal:hover:not(:disabled) { background: var(--cyan-dark); }
.btn--amber { background: var(--amber); color: var(--amber-ink); }
.btn--amber:hover:not(:disabled) { background: #E9A538; }
.btn--ghost{
  background: transparent; color: var(--navy-mid);
  border: 1px solid rgba(18, 34, 47, .3); font-weight: 600; padding: 15px 22px;
}
.btn--ghost:hover:not(:disabled) { border-color: var(--navy-mid); }
.btn--link{
  background: transparent; border: none; padding: 0;
  color: var(--rust); font-size: 15px; font-weight: 600; cursor: pointer;
}
.btn--link:hover:not(:disabled) { text-decoration: underline; }

.file-btn{
  background: var(--cyan-deep); color: #fff; border-radius: 8px;
  padding: 14px 22px; font-size: 16px; font-weight: 600; cursor: pointer;
  display: inline-block;
}
.file-btn:hover { background: var(--cyan-dark); }
.file-btn input { position: absolute; width: 1px; height: 1px; opacity: 0; }

.chips { display: flex; flex-wrap: wrap; gap: 10px; }
.chip{
  border: 1px solid rgba(18, 34, 47, .28); border-radius: 100px;
  padding: 10px 18px; font-size: 15px; font-weight: 600;
  background: transparent; color: var(--ink); cursor: pointer;
}
.chip[aria-pressed="true"] { background: var(--navy-mid); color: #fff; border-color: var(--navy-mid); }

.note { font-size: 15px; color: var(--muted); margin: 0; }

.status { margin: 0; font-size: 15px; font-weight: 600; min-height: 1.5em; color: var(--cyan-dark); }
.status--warn { color: var(--rust); }

/* ── Sheet queue list ───────────────────────────────────── */

.queue { display: flex; flex-wrap: wrap; gap: 10px; list-style: none; margin: 0; padding: 0; }
.queue__item{
  display: flex; align-items: center; gap: 10px;
  background: #fff; border-radius: 100px;
  padding: 9px 8px 9px 16px; font-size: 15px;
}
.queue__remove{
  border: none; background: rgba(18, 34, 47, .08); border-radius: 50%;
  width: 24px; height: 24px; cursor: pointer; color: var(--ink);
  font-size: 14px; line-height: 1; padding: 0;
}
.queue__remove:hover { background: rgba(18, 34, 47, .18); }

/* ============================================================
   The name tag itself — one component, two pages.

   Every dimension is a multiple of --u, so one markup serves both the
   screen preview and the printed sheet; only --u changes between them.
   Its printed value comes from --tag-width at the top of this file.
   ============================================================ */

/* Browsers drop background colours and background-images from printouts
   unless the user ticks "Background graphics". The tag's sand backdrop and
   the check-in photo are both backgrounds, so force them on — otherwise the
   sheet prints as bare text on white. Inherited, hence the descendants too. */
.tag, .tag *{
  -webkit-print-color-adjust: exact;
          print-color-adjust: exact;
  /* Windows High Contrast would otherwise repaint the tag in system colours. */
  forced-color-adjust: none;
}

.tag{
  --u: var(--u-print);
  position: relative; overflow: hidden;
  width:  calc(var(--u) * var(--tag-cols));
  height: calc(var(--u) * var(--tag-rows));
  background: #C9A87C;
  color: #2A2118;
  box-shadow: 0 18px 40px rgba(18, 34, 47, .18);
  padding: calc(var(--u) * 21) calc(var(--u) * 21) calc(var(--u) * 23);
  display: flex; flex-direction: column; align-items: center;
  justify-content: space-between; text-align: center;
}
.tag__glow{
  position: absolute; inset: 0;
  background: radial-gradient(90% 45% at 50% 0%, rgba(14, 110, 134, .18) 0%, rgba(14, 110, 134, 0) 60%);
}
.tag__punch{
  position: relative;
  width: calc(var(--u) * 49); height: calc(var(--u) * 10);
  border: 1.5px dashed rgba(27, 44, 56, .45);
  border-radius: 100px;
}
.tag__head{
  position: relative;
  display: flex; flex-direction: column; align-items: center;
  gap: calc(var(--u) * 6);
}
.tag__logo { display: flex; align-items: center; gap: calc(var(--u) * 7); }
.tag__logo-a{
  font-family: var(--font-display); font-weight: 800;
  font-size: calc(var(--u) * 16); color: #12222F;
}
.tag__logo-a span { color: #0E6E86; }
.tag__logo-rule { width: 1px; height: calc(var(--u) * 13); background: rgba(27, 44, 56, .35); }
.tag__logo-b{
  font-family: var(--font-display); font-weight: 600;
  font-size: calc(var(--u) * 14); color: #7A5A32;
}
.tag__t1 { font-size: calc(var(--u) * 16); line-height: 1.25; font-weight: 600; color: #12222F; }
.tag__t2 { font-size: calc(var(--u) * 16); line-height: 1.25; color: #7A5A32; }
.tag__photo{
  position: relative; overflow: hidden;
  width: calc(var(--u) * 153); height: calc(var(--u) * 153);
  border-radius: 50%;
  border: 2px solid rgba(27, 44, 56, .45);
  display: flex; align-items: center; justify-content: center;
  background: rgba(255, 255, 255, .4);
}
.tag__photo--filled { background-color: transparent; }
/* Own layer so a print filter hits the photo and not the ring around it. */
.tag__photo-img{
  position: absolute; inset: 0;
  background-repeat: no-repeat;
  filter: var(--photo-filter, none);
}
.tag__photo-hint{
  position: relative;
  font-size: calc(var(--u) * 12); color: rgba(27, 44, 56, .55);
}
.tag__txt{
  position: relative;
  display: flex; flex-direction: column; gap: calc(var(--u) * 6);
  width: 100%;
}
.tag__name{
  font-family: var(--font-display); font-weight: 800;
  font-size: calc(var(--u) * 33); line-height: 1.02; color: #12222F;
  overflow-wrap: break-word;
}
.tag__name--long { font-size: calc(var(--u) * 25); }
.tag__skill{
  font-size: calc(var(--u) * 16); line-height: 1.3;
  color: #0E6E86; font-weight: 600;
  overflow-wrap: break-word;
}
/* Several skills joined by "|" outgrow one line at full size. */
.tag__skill--long { font-size: calc(var(--u) * 13); }
.tag__qr{
  position: relative;
  display: flex; align-items: center; gap: calc(var(--u) * 10);
}
/* 72u = 19.2mm printed. The event QR is a version-8 symbol (49 x 49
   modules), so at the 59u the design originally called for each module
   would land at 0.289mm — under what a phone camera reliably reads, and
   well under what toner holds on kraft. 72u lifts it to 0.36mm. */
.tag__qr-slot{
  position: relative;
  width: calc(var(--u) * 72); height: calc(var(--u) * 72);
  background: #fff; border-radius: calc(var(--u) * 5);
  display: flex; align-items: center; justify-content: center;
}
/* Shows through only while assets/img/qr-event.png is absent. */
.tag__qr-slot span{
  font-size: calc(var(--u) * 13); font-weight: 700; letter-spacing: .1em;
  color: rgba(27, 44, 56, .35);
  border: 1px dashed rgba(27, 44, 56, .3);
  border-radius: calc(var(--u) * 3);
  padding: calc(var(--u) * 6) calc(var(--u) * 8);
}
/* Opaque and covering the whole slot, so a loaded QR hides the placeholder
   with no JS involved. Stays an <img> rather than a background-image because
   browsers drop background graphics from printouts by default. */
.tag__qr-slot img{
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  background: #fff;
  border-radius: calc(var(--u) * 5);
  padding: calc(var(--u) * 3);
}
.tag__qr-label{
  text-align: left; font-size: calc(var(--u) * 16); line-height: 1.3;
  color: rgba(27, 44, 56, .72); font-weight: 600;
}

/* Placeholder state — no photo picked yet. */
.tag--empty .tag__name, .tag--empty .tag__skill { color: rgba(27, 44, 56, .5); }

/* ============================================================
   Print modes.

   Registration is the whole game here: a tag printed in `content` mode has
   to land exactly on top of the same tag printed earlier in `template`
   mode. So neither mode removes a single box — every element stays in flow
   and is hidden with `visibility`, which reserves its space. Using
   `display:none` would let the flex column re-distribute and the two passes
   would no longer line up.
   ============================================================ */

/* Who owns the photo circle: the CONTENT layer, in every workflow. Both
   phôi modes hide it entirely, so the ring is drawn exactly once and can
   never double-print slightly off-register. */

/* Phôi giấy trắng: the full artwork, guest area left blank. */
.sheet--template .tag__photo,
.sheet--template .tag__name,
.sheet--template .tag__skill { visibility: hidden; }

/* Phôi giấy kraft: same fixed ink minus every background — the paper is
   already the colour — leaving the cut border as the only frame. */
.sheet--kraft .tag{
  background: transparent;
  box-shadow: none;
}
.sheet--kraft .tag__glow,
.sheet--kraft .tag__photo,
.sheet--kraft .tag__name,
.sheet--kraft .tag__skill { visibility: hidden; }

/* In lên phôi: the variable data plus its own circle, on bare paper. */
.sheet--content .tag{
  background: transparent;
  box-shadow: none;
}
.sheet--content .tag__glow,
.sheet--content .tag__punch,
.sheet--content .tag__head,
.sheet--content .tag__qr { visibility: hidden; }
.sheet--content .tag__photo{
  background-color: transparent;   /* no white disc on a guest with no photo */
}
.sheet--content .tag__photo-hint { visibility: hidden; }

/* ── Bù mực cho giấy kraft ──────────────────────────────────
   A printer only ever adds ink; it cannot lay down white or lighten the
   stock. Measured against kraft (#C4A484) the design's two mid-tone inks
   land at 2.5:1 and 2.7:1 — legible on a backlit screen, mud on paper.
   This block pushes just those two down to ~5.5:1 and leaves the navy and
   the QR black alone, since they already clear 6.9:1.
   ─────────────────────────────────────────────────────────── */
.is-kraft-ink .tag__logo-b,
.is-kraft-ink .tag__t2,
.is-kraft-ink .tag__qr-label { color: #402E17; }
.is-kraft-ink .tag__logo-a span,
.is-kraft-ink .tag__skill { color: #0B4A5C; }
.is-kraft-ink .tag__photo { border-color: rgba(27, 44, 56, .75); }
/* The glow is a pale wash — invisible on brown, and it only muddies. */
.is-kraft-ink .tag__glow { display: none; }

/* On screen these modes would otherwise be invisible rectangles. */
.workbench__preview .sheet--content .tag,
.workbench__preview .sheet--template .tag,
.workbench__preview .sheet--kraft .tag{
  outline: 1px dashed rgba(18, 34, 47, .35);
  outline-offset: -1px;
  box-shadow: none;
}
/* Preview only — simulates the kraft stock so the ink can be judged
   against brown paper. Nothing here reaches the printer. */
.workbench__preview .is-kraft-ink .tag,
.workbench__preview .sheet--kraft .tag { background: var(--paper, #C4A484); }

/* ── Print: A4 portrait, 4 tags per sheet ───────────────── */

@page { size: A4 portrait; margin: 6mm; }

.print-only { display: none; }

@media print{
  body { background: #fff; }
  .no-print { display: none !important; }
  .page { padding: 0; gap: 0; min-height: 0; }

  .print-only { display: block; }

  /* Each row of tags is centred inside its own half of the A4 rather than
     stacked from the top margin, so a cut straight across the middle
     leaves two tidy A5 pieces with the tags well clear of the edge.

       row inset from the half's edge = (148.5 - 133) / 2 = 7.75mm
       gap between rows               =  148.5 - 133      = 15.5mm
       sheet height                   =  283.25mm  (A4 printable: 285mm)

     Rows sit at fixed offsets, which is what lets the two halves be
     printed in separate passes: the sheet goes back into the tray whole
     and uncut, and a tag printed on the second pass lands exactly where
     it would have if all four had gone down at once. */
  .sheet{
    --u: var(--u-print);
    --tag-h: calc(var(--u) * var(--tag-rows));
    --row-inset: calc((var(--a5-half) - var(--tag-h)) / 2);

    display: grid;
    grid-template-columns: repeat(2, calc(var(--u) * var(--tag-cols)));
    grid-auto-rows: var(--tag-h);
    column-gap: 10mm;
    row-gap: calc(var(--a5-half) - var(--tag-h));
    padding-top: calc(var(--row-inset) - var(--page-margin));
    width: max-content;
    margin: 0 auto;
    break-inside: avoid;
  }
  .sheet + .sheet { break-before: page; }

  /* Spans the sheet exactly rather than bleeding past it — at a 6mm page
     margin, overhang would land in the printer's unprintable strip. */
  .sheet__cut{
    left: 0; right: 0;
    top: calc(var(--a5-half) - var(--page-margin));
    border-top: 1px dashed rgba(27, 44, 56, .55);
    text-align: center;
  }
  .sheet__cut span{
    position: relative; top: -2.2mm;
    background: #fff; padding: 0 2mm;
    font-size: 7pt; letter-spacing: .14em;
    color: rgba(27, 44, 56, .6);
  }

  .sheet .tag{
    box-shadow: none;
    outline: 1px dashed rgba(27, 44, 56, .35);
    outline-offset: -1px;
  }
  /* The cut guide is already on the phôi — don't lay a second one over it. */
  .sheet--content .tag { outline: none; }

  /* On kraft the cut line is the only frame on the sheet, so it has to
     read against brown paper rather than sit at artwork-guide weight. */
  .sheet--kraft .tag { outline-color: rgba(27, 44, 56, .8); }
}
