/* ====================================================================
   Hubbard Martial Arts Academy — marketing site
   Tokens are semantic (--bg, --text, --accent…) and re-mapped per theme.
   ==================================================================== */

:root{
  /* raw palette */
  --ink:        #14171c;
  --ink-soft:   #1b1f26;
  --ink-line:   rgba(238,240,236,0.14);
  --paper:      #eef0ec;
  --paper-soft: #e2e5de;
  --paper-line: rgba(20,23,28,0.12);
  --red:        #c8102e;
  --red-dim:    #8f0c22;
  --blue:       #0b3d78;
  --gold:       #b08d3e;

  /* type */
  --font-display: Georgia, "Iowan Old Style", "Noto Serif", "Times New Roman", serif;
  --font-body: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;

  --fs-eyebrow: 0.78rem;
  --fs-body: 1.0625rem;
  --fs-lead: clamp(1.125rem, 1.02rem + 0.4vw, 1.3rem);
  --fs-h3: clamp(1.15rem, 1rem + 0.6vw, 1.4rem);
  --fs-h2: clamp(1.9rem, 1.4rem + 2vw, 2.85rem);
  --fs-h1: clamp(2.6rem, 1.7rem + 5vw, 5.2rem);
  --fs-quote: clamp(1.2rem, 1.05rem + 0.8vw, 1.55rem);

  --space-1: 0.5rem;
  --space-2: 1rem;
  --space-3: 1.5rem;
  --space-4: 2.25rem;
  --space-5: 3.5rem;
  --space-6: 5.5rem;
  --space-7: 8rem;

  --radius-sm: 3px;
  --radius-pill: 999px;
  --max: 1180px;

  --ease: cubic-bezier(.22,.61,.36,1);

  /* semantic — light default */
  --bg: var(--paper);
  --bg-elevated: var(--paper-soft);
  --text: #1b1e1a;
  --text-muted: rgba(27,30,26,0.66);
  --border: var(--paper-line);
  --accent: var(--red);
  --accent-2: var(--blue);
  --on-accent: var(--paper);
  --nav-bg: rgba(238,240,236,0.86);
}

@media (prefers-color-scheme: dark){
  :root{
    --bg: var(--ink);
    --bg-elevated: var(--ink-soft);
    --text: var(--paper);
    --text-muted: rgba(238,240,236,0.66);
    --border: var(--ink-line);
    --accent: var(--red);
    --accent-2: #4d7fc4;
    --on-accent: var(--paper);
    --nav-bg: rgba(20,23,28,0.82);
  }
}
:root[data-theme="dark"]{
  --bg: var(--ink);
  --bg-elevated: var(--ink-soft);
  --text: var(--paper);
  --text-muted: rgba(238,240,236,0.66);
  --border: var(--ink-line);
  --accent: var(--red);
  --accent-2: #4d7fc4;
  --on-accent: var(--paper);
  --nav-bg: rgba(20,23,28,0.82);
}
:root[data-theme="light"]{
  --bg: var(--paper);
  --bg-elevated: var(--paper-soft);
  --text: #1b1e1a;
  --text-muted: rgba(27,30,26,0.66);
  --border: var(--paper-line);
  --accent: var(--red);
  --accent-2: var(--blue);
  --on-accent: var(--paper);
  --nav-bg: rgba(238,240,236,0.86);
}

*,*::before,*::after{ box-sizing: border-box; }
html{ scroll-behavior: smooth; }
@media (prefers-reduced-motion: reduce){
  html{ scroll-behavior: auto; }
  *,*::before,*::after{ animation-duration: 0.001ms !important; animation-iteration-count: 1 !important; transition-duration: 0.001ms !important; }
}

body{
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font-family: var(--font-body);
  font-size: var(--fs-body);
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
  transition: background .3s var(--ease), color .3s var(--ease);
}

h1,h2,h3{ font-family: var(--font-display); font-weight: 700; margin: 0; text-wrap: balance; }
p{ margin: 0; }
ul,ol{ margin: 0; padding: 0; list-style: none; }
a{ color: inherit; text-decoration: none; }
button{ font: inherit; color: inherit; background: none; border: none; cursor: pointer; }
table{ border-collapse: collapse; }

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

.skip-link{
  position: absolute; left: -999px; top: 0;
  background: var(--accent); color: var(--on-accent);
  padding: 0.75rem 1.25rem; z-index: 200;
}
.skip-link:focus{ left: var(--space-3); top: var(--space-2); }

:focus-visible{ outline: 2px solid var(--accent); outline-offset: 3px; }

/* ---------- Nav ---------- */
.site-nav{
  position: sticky; top: 0; z-index: 100;
  border-bottom: 1px solid transparent;
  transition: border-color .3s var(--ease);
}
.site-nav.is-scrolled{ border-bottom-color: var(--border); }
/* backdrop-filter lives on a pseudo-element, not .site-nav itself, because
   filter/backdrop-filter on an ancestor redefines the containing block for
   any position:fixed descendant (the mobile nav drawer) — putting it here
   keeps the fixed drawer anchored to the viewport instead of the navbar. */
.site-nav::before{
  content: ""; position: absolute; inset: 0; z-index: -1;
  background: var(--nav-bg);
  backdrop-filter: saturate(140%) blur(10px);
}
.nav-inner{
  display: flex; align-items: center; justify-content: space-between;
  padding-top: var(--space-2); padding-bottom: var(--space-2);
}
/* Wordmark is a lockup: the academy's logo, then the name stacked over two
   lines. Two lines rather than one because the full name set at .wordmark-en's
   size is ~270px wide, which collides with the hamburger on a 360px phone. */
.wordmark{ display: flex; align-items: center; gap: 0.6rem; }
.wordmark-logo{
  width: 42px; height: 42px; flex: none;
  /* The logo's outer ring is near-black and disappears against the dark nav;
     a hairline halo keeps its silhouette readable on both themes. */
  border-radius: 50%;
  box-shadow: 0 0 0 1px var(--border);
}
.wordmark-lines{ display: flex; flex-direction: column; line-height: 1.12; }
.wordmark-top{ display: flex; align-items: baseline; gap: 0.45rem; }
.wordmark-en{
  font-family: var(--font-body); font-weight: 800; letter-spacing: 0.06em;
  font-size: 1.05rem;
}
.wordmark-kr{
  font-family: var(--font-display); font-style: italic; color: var(--accent);
  font-size: 0.95rem;
}
.wordmark-sub{
  font-family: var(--font-body); font-weight: 600; text-transform: uppercase;
  letter-spacing: 0.17em; font-size: 0.6rem; color: var(--text-muted);
  white-space: nowrap;
}
@media (max-width: 420px){
  .wordmark-logo{ width: 36px; height: 36px; }
  .wordmark-en{ font-size: 0.95rem; }
  .wordmark-kr{ display: none; }
  .wordmark-sub{ font-size: 0.55rem; letter-spacing: 0.14em; }
}
.primary-nav{ display: flex; align-items: center; gap: var(--space-4); }
.primary-nav a{
  font-size: 0.92rem; font-weight: 500; color: var(--text-muted);
  transition: color .2s var(--ease);
}
.primary-nav a:hover{ color: var(--text); }
.nav-cta{
  color: var(--on-accent) !important; background: var(--accent);
  padding: 0.55rem 1.1rem; border-radius: var(--radius-pill);
  font-weight: 700 !important;
}
.nav-toggle{
  display: none; flex-direction: column; gap: 5px; padding: 0.5rem;
}
.nav-toggle span{ width: 22px; height: 2px; background: var(--text); display: block; transition: transform .25s var(--ease), opacity .25s var(--ease); }
.nav-toggle[aria-expanded="true"] span:nth-child(1){ transform: translateY(7px) rotate(45deg); }
.nav-toggle[aria-expanded="true"] span:nth-child(2){ opacity: 0; }
.nav-toggle[aria-expanded="true"] span:nth-child(3){ transform: translateY(-7px) rotate(-45deg); }

/* ---------- Hero ---------- */
.hero{
  position: relative; overflow: hidden;
  background: var(--ink); color: var(--paper);
  padding: var(--space-7) 0 var(--space-6);
  min-height: 78vh; display: flex; align-items: center;
}
/* Real photo of a class behind the hero. Two stacked declarations rather than
   one: the plain url() is the fallback, and any browser that understands
   image-set() overrides it with the ~50%-smaller WebP. */
.hero::before{
  content: ""; position: absolute; inset: 0; z-index: 0;
  background-image: url("../img/hero.jpg");
  background-image: image-set(url("../img/hero.webp") type("image/webp"),
                              url("../img/hero.jpg")  type("image/jpeg"));
  background-size: cover; background-position: 72% 32%;
  opacity: 0.45;
}
/* Scrim so the headline keeps contrast over whatever the photo is doing
   underneath. Heavier on the left, where the text actually sits. */
.hero::after{
  content: ""; position: absolute; inset: 0; z-index: 1;
  background:
    linear-gradient(100deg, rgba(20,23,28,0.94) 0%, rgba(20,23,28,0.78) 42%, rgba(20,23,28,0.32) 100%),
    linear-gradient(to top, rgba(20,23,28,0.85) 0%, rgba(20,23,28,0) 45%);
}
.hero .eyebrow{ color: rgba(238,240,236,0.6); }
/* Hidden now that the hero carries a real photograph. The canvas taegeuk was
   the focal point when the hero was flat dark ink; over a photo it bleeds off
   the right edge and reads as a cut-off coloured blob rather than a symbol.
   The element and its canvas drawing in main.js are kept (not deleted) so the
   mark can be restored if a future hero goes back to a plain background. */
.taegeuk{ display: none; }
@media (prefers-reduced-motion: reduce){ .taegeuk{ animation: none; } }
@keyframes spin{ to{ transform: translateY(-50%) rotate(360deg); } }
.hero-inner{ position: relative; z-index: 3; max-width: 640px; }
.hero-title{ font-size: var(--fs-h1); line-height: 0.98; margin: var(--space-2) 0 var(--space-3); color: var(--paper); }
.hero-lead{ font-size: var(--fs-lead); color: rgba(238,240,236,0.82); max-width: 46ch; }
.hero-actions{ display: flex; flex-wrap: wrap; gap: var(--space-2); margin-top: var(--space-4); }

.eyebrow{
  font-family: var(--font-body); font-size: var(--fs-eyebrow); font-weight: 700;
  text-transform: uppercase; letter-spacing: 0.14em; color: var(--accent);
  margin: 0 0 var(--space-1);
}

.btn{
  display: inline-flex; align-items: center; justify-content: center;
  padding: 0.85rem 1.6rem; border-radius: var(--radius-pill);
  font-weight: 700; font-size: 0.95rem; transition: transform .2s var(--ease), background .2s var(--ease), border-color .2s var(--ease);
}
.btn:hover{ transform: translateY(-2px); }
.btn-primary{ background: var(--accent); color: var(--on-accent); }
.btn-primary:hover{ background: var(--red-dim); }
.btn-ghost{ border: 1px solid rgba(238,240,236,0.4); color: var(--paper); }
.btn-ghost:hover{ border-color: var(--paper); }
.btn-block{ width: 100%; }

.belt-rule{
  height: 8px;
  border-top: 1px solid rgba(0,0,0,0.25);
  border-bottom: 1px solid rgba(0,0,0,0.25);
  background: linear-gradient(90deg,
    #f5f4f0 0 11.1%, #e8b923 11.1% 22.2%, #e5822a 22.2% 33.3%,
    #2f7a3c 33.3% 44.4%, #1f5fa8 44.4% 55.5%, #6a4c93 55.5% 66.6%,
    #6b4a2b 66.6% 77.7%, #c8102e 77.7% 88.8%, #16161a 88.8% 100%);
}

/* ---------- Sections ---------- */
.section{ padding: var(--space-6) 0; }
.section-alt{ background: var(--bg-elevated); }
.section-head{ max-width: 62ch; margin-bottom: var(--space-5); }
.section-head h2{ font-size: var(--fs-h2); margin-bottom: var(--space-2); }
.section-lead{ font-size: var(--fs-lead); color: var(--text-muted); }

.reveal{ opacity: 0; transform: translateY(18px); transition: opacity .6s var(--ease), transform .6s var(--ease); }
.reveal.is-visible{ opacity: 1; transform: none; }
@media (prefers-reduced-motion: reduce){ .reveal{ opacity: 1; transform: none; } }

/* ---------- Tenets ---------- */
.tenets-list{ border-top: 1px solid var(--border); }
.tenet{
  display: grid; grid-template-columns: 3.5rem 1fr;
  gap: var(--space-3); padding: var(--space-3) 0;
  border-bottom: 1px solid var(--border);
}
.tenet-num{ font-family: var(--font-display); font-size: 1.6rem; color: var(--accent); font-style: italic; }
.tenet-body h3{ font-size: var(--fs-h3); margin-bottom: 0.35rem; }
.tenet-kr{ color: var(--text-muted); font-weight: 400; font-size: 0.85em; }
.tenet-body p{ color: var(--text-muted); max-width: 60ch; }

/* ---------- Curriculum board ---------- */
.board{ border-top: 1px solid var(--border); }
.board-row{
  display: grid; grid-template-columns: 92px 1.1fr 0.6fr 2fr 1fr;
  gap: var(--space-3); padding: var(--space-2) 0;
  border-bottom: 1px solid var(--border); align-items: center;
}
/* One real photo per age band — a parent scanning this page is looking for
   children who look like theirs, which no amount of copy substitutes for. */
.board-thumb{ display: block; }
/* height:auto is required, not cosmetic. The <img> carries width/height
   attributes (which prevent layout shift while loading), and those act as
   presentational hints setting height:540px. aspect-ratio only computes a
   dimension that is auto, so without this the ratio is ignored and the
   thumbnail renders as a 92x540 vertical sliver. */
.board-thumb img{
  display: block; width: 100%; height: auto;
  aspect-ratio: 4 / 3; object-fit: cover;
  border-radius: var(--radius-sm);
}
.board-head{
  font-size: 0.78rem; text-transform: uppercase; letter-spacing: 0.1em;
  color: var(--text-muted); font-weight: 700;
}
.board-program{ font-family: var(--font-display); font-weight: 700; font-size: 1.05rem; }
.board-row:not(.board-head) [data-label]{ color: var(--text-muted); }
.board-belts{ display: flex; gap: 0.35rem; }
.dot{ width: 12px; height: 12px; border-radius: 50%; display: inline-block; border: 1px solid var(--border); }
.dot-white{ background:#f5f4f0; } .dot-yellow{ background:#e8b923; } .dot-orange{ background:#e5822a; }
.dot-green{ background:#2f7a3c; } .dot-blue{ background:#1f5fa8; } .dot-purple{ background:#6a4c93; }
.dot-brown{ background:#6b4a2b; } .dot-red{ background:#c8102e; } .dot-black{ background:#16161a; }

/* ---------- Belt strip ---------- */
.belt-strip{ display: flex; flex-wrap: wrap; border-radius: var(--radius-sm); overflow: hidden; }
.belt-seg{
  flex: 1 1 11%; min-width: 90px; background: var(--belt-color); color: var(--belt-text);
  padding: var(--space-3) var(--space-2); text-align: center; cursor: pointer;
  transition: flex-grow .25s var(--ease), filter .2s var(--ease);
  border-right: 1px solid rgba(0,0,0,0.15);
}
.belt-seg:last-child{ border-right: none; }
.belt-seg:hover, .belt-seg:focus-visible, .belt-seg.is-active{ flex-grow: 1.8; filter: brightness(1.08); }
.belt-name{ font-weight: 700; font-size: 0.85rem; text-transform: uppercase; letter-spacing: 0.06em; }
.belt-detail{
  margin-top: var(--space-3); min-height: 2.6em; color: var(--text-muted);
  font-size: var(--fs-lead); max-width: 60ch;
}

/* ---------- Roster ---------- */
.roster{ border-top: 1px solid var(--border); }
.roster-row{
  display: flex; gap: var(--space-3); align-items: flex-start;
  padding: var(--space-3) 0; border-bottom: 1px solid var(--border);
}
.avatar{
  flex: none; width: 3.25rem; height: 3.25rem; border-radius: 50%;
  background: var(--accent); color: var(--on-accent);
  display: flex; align-items: center; justify-content: center;
  font-family: var(--font-display); font-weight: 700; font-size: 1.05rem;
}
.avatar-photo{ flex: none; display: block; }
.avatar-photo img{
  display: block; width: 10rem; height: 10rem; border-radius: 50%;
  object-fit: cover; object-position: center 12%;
  border: 2px solid var(--border);
}
.roster-body h3{ font-size: var(--fs-h3); margin-bottom: 0.25rem; }
.rank{ font-family: var(--font-body); font-weight: 500; font-size: 0.75rem; text-transform: uppercase;
  letter-spacing: 0.08em; color: var(--text-muted); margin-left: 0.6rem; }
.roster-body p{ color: var(--text-muted); max-width: 60ch; }

/* ---------- Schedule ---------- */
.table-scroll{ overflow-x: auto; border-top: 1px solid var(--border); }
.schedule-table{ width: 100%; min-width: 560px; }
.schedule-table th, .schedule-table td{
  padding: var(--space-2); text-align: left; border-bottom: 1px solid var(--border);
  font-variant-numeric: tabular-nums; font-size: 0.92rem;
}
.schedule-table thead th{
  text-transform: uppercase; letter-spacing: 0.08em; font-size: 0.72rem; color: var(--text-muted);
}
.schedule-table tbody th{ font-weight: 700; }
.schedule-table td{ color: var(--text-muted); }

/* ---------- Testimonials ---------- */
.quote-strip{ display: grid; gap: var(--space-4); grid-template-columns: repeat(3,1fr); }
.quote{ border-top: 3px solid var(--accent); padding-top: var(--space-2); }
.quote p{
  font-family: var(--font-display); font-style: italic; font-size: var(--fs-quote);
  margin-bottom: var(--space-2);
}
.quote cite{ font-style: normal; font-size: 0.85rem; color: var(--text-muted); }

/* ---------- Contact ----------
   minmax(0,1fr) rather than 1fr throughout this block, deliberately. Grid's
   `1fr` is shorthand for minmax(auto,1fr), and `auto` there means MIN-CONTENT
   — so a track containing an <input> can never shrink below that input's
   intrinsic ~20-character width. Two of them side by side in .form-row-split
   floored the form at ~522px, which floored this grid's column, which floored
   .wrap, and pushed the whole document to 619px inside a 360px viewport: the
   page rendered zoomed-out with everything out of shape. minmax(0,…) lets the
   tracks actually shrink; the width/min-width on the controls below stops them
   re-asserting their intrinsic size once the track allows it. */
.contact-grid{ display: grid; grid-template-columns: minmax(0,1fr) minmax(0,1fr); gap: var(--space-6); align-items: start; }
.contact-facts{ margin-top: var(--space-4); display: flex; flex-direction: column; gap: var(--space-2); }
.contact-facts div{ display: flex; flex-direction: column; }
.contact-facts dt{ font-size: 0.72rem; text-transform: uppercase; letter-spacing: 0.1em; color: var(--text-muted); }
.contact-facts dd{ margin: 0; font-weight: 600; }

.trial-form{ background: var(--bg-elevated); border: 1px solid var(--border); padding: var(--space-4); border-radius: var(--radius-sm); }
.form-row{ display: flex; flex-direction: column; gap: 0.4rem; margin-bottom: var(--space-3); }
.form-row-split{ display: grid; grid-template-columns: minmax(0,1fr) minmax(0,1fr); gap: var(--space-3); }
.form-row-split > div{ display: flex; flex-direction: column; gap: 0.4rem; min-width: 0; }
.trial-form label{ font-size: 0.8rem; font-weight: 600; }
.trial-form input, .trial-form select{
  font: inherit; padding: 0.7rem 0.8rem; border: 1px solid var(--border);
  border-radius: var(--radius-sm); background: var(--bg); color: var(--text);
  /* width+min-width are what actually stop an input asserting its intrinsic
     size; box-sizing:border-box is already set globally so 100% is safe.
     font:inherit also keeps these at 17px — under 16px, iOS Safari zooms the
     viewport on focus and never zooms back out. */
  width: 100%; min-width: 0;
}
.trial-form input:focus, .trial-form select:focus{ outline: 2px solid var(--accent); outline-offset: 1px; }
.form-note{ margin-top: var(--space-2); font-size: 0.78rem; color: var(--text-muted); text-align: center; }
.form-success{ text-align: center; padding: var(--space-4) 0; }
.form-success h3{ font-size: var(--fs-h3); margin-bottom: var(--space-1); }
.form-success p{ color: var(--text-muted); }

/* ---------- Gallery ---------- */
.gallery{ display: grid; grid-template-columns: repeat(4, 1fr); gap: var(--space-2); }
.gallery figure{ margin: 0; }
.gallery img{
  display: block; width: 100%; height: auto;  /* see .board-thumb img */
  aspect-ratio: 4 / 3; object-fit: cover;
  border-radius: var(--radius-sm);
}
.gallery figcaption{ margin-top: 0.5rem; font-size: 0.8rem; color: var(--text-muted); }

/* ---------- Location map ---------- */
.map-band{ padding-bottom: var(--space-5); }
.map-head{ margin-bottom: var(--space-3); }
/* Aspect-ratio box rather than a fixed height: the embed has to stay usable
   from a 320px phone up to the 1200px wrap without letterboxing. */
.map-frame{
  position: relative; aspect-ratio: 16 / 7; min-height: 240px;
  border: 1px solid var(--border); border-radius: var(--radius-sm);
  overflow: hidden; background: var(--bg-elevated);
}
.map-frame iframe{ position: absolute; inset: 0; width: 100%; height: 100%; border: 0; }
.map-link{ margin-top: var(--space-2); font-weight: 600; }
@media (max-width: 640px){
  .map-frame{ aspect-ratio: 4 / 3; }
}

/* ---------- Footer ---------- */
.site-footer{ background: var(--ink); color: var(--paper); padding: var(--space-5) 0 var(--space-3); }
.footer-inner{ display: flex; justify-content: space-between; flex-wrap: wrap; gap: var(--space-4); }
.footer-tenets{ margin-top: var(--space-1); font-size: 0.78rem; color: rgba(238,240,236,0.55); }
.footer-links{ display: flex; gap: var(--space-3); flex-wrap: wrap; }
.footer-links a{ color: rgba(238,240,236,0.75); font-size: 0.9rem; }
.footer-links a:hover{ color: var(--paper); }
.footer-fine{ width: 100%; font-size: 0.76rem; color: rgba(238,240,236,0.45); border-top: 1px solid var(--ink-line); padding-top: var(--space-3); margin-top: var(--space-2); }


/* ---------- Zoomable photos ----------
   Each thumbnail is wrapped in a real <button>, not a div with a click
   handler, so keyboard and screen-reader users get focus and Enter/Space
   for free rather than having them re-implemented badly. */
.zoom{
  display: block; width: 100%; padding: 0; border: 0; background: none;
  cursor: zoom-in; border-radius: var(--radius-sm); overflow: hidden;
  -webkit-tap-highlight-color: transparent;
}
.zoom img{ transition: transform .35s var(--ease), filter .35s var(--ease); }
.zoom:hover img{ transform: scale(1.03); filter: brightness(1.06); }
.zoom:focus-visible{ outline: 2px solid var(--accent); outline-offset: 3px; }
/* The portrait is a fixed circle, so it must not inherit .zoom's width:100%. */
.zoom.avatar-photo{ width: auto; border-radius: 50%; }
@media (prefers-reduced-motion: reduce){
  .zoom img{ transition: none; }
  .zoom:hover img{ transform: none; }
}

/* ---------- Lightbox ---------- */
.lightbox{
  position: fixed; inset: 0; z-index: 300;
  background: rgba(10,12,15,0.94);
  display: flex; align-items: center; justify-content: center;
  padding: max(14px, env(safe-area-inset-top)) 14px max(14px, env(safe-area-inset-bottom));
}
.lightbox[hidden]{ display: none; }
.lightbox-figure{ margin: 0; display: flex; flex-direction: column; align-items: center; gap: 0.75rem; max-width: 100%; }
.lightbox-figure img{
  display: block; max-width: min(94vw, 1100px); max-height: 78vh;
  width: auto; height: auto; object-fit: contain;
  border-radius: 3px; background: #14171c;
}
.lightbox-figure figcaption{
  color: rgba(238,240,236,0.8); font-size: 0.9rem; text-align: center; max-width: 46ch;
}
/* 44px minimum so these are usable with a thumb, not just a mouse. */
.lightbox-btn{
  position: absolute; display: flex; align-items: center; justify-content: center;
  width: 48px; height: 48px; border-radius: 50%;
  background: rgba(238,240,236,0.1); color: var(--paper);
  border: 1px solid rgba(238,240,236,0.22);
  font-size: 1.4rem; line-height: 1;
}
.lightbox-btn:hover{ background: rgba(238,240,236,0.2); }
.lightbox-btn:focus-visible{ outline: 2px solid var(--paper); outline-offset: 2px; }
.lightbox-close{ top: 14px; right: 14px; font-size: 1.1rem; }
.lightbox-prev{ left: 14px; top: 50%; transform: translateY(-50%); }
.lightbox-next{ right: 14px; top: 50%; transform: translateY(-50%); }
.lightbox-count{
  position: absolute; bottom: 16px; left: 50%; transform: translateX(-50%);
  color: rgba(238,240,236,0.55); font-size: 0.78rem; letter-spacing: 0.06em;
}
@media (max-width: 860px){
  /* Side arrows would sit over the photo on a narrow screen, so they move
     to the bottom edge where a thumb actually reaches. */
  .lightbox-figure img{ max-height: 64vh; }
  .lightbox-prev{ left: 22%; top: auto; bottom: 46px; transform: none; }
  .lightbox-next{ right: 22%; top: auto; bottom: 46px; transform: none; }
  .lightbox-count{ bottom: 62px; }
}

/* ---------- Pre-launch placeholder marker ----------
   Wraps any block whose content is still unverified. Deliberately loud: the
   whole point is that this site is about to be pointed at a real business's
   domain, and nobody should be able to publish invented instructors, class
   times, or testimonials without noticing. Delete the wrapping div (not this
   rule) as each section gets real content; when the stylesheet's .needs-content
   blocks are all gone, the site is content-complete.
   Suppressed in print so client PDF proofs stay clean. */
.needs-content{
  position: relative;
  outline: 2px dashed var(--gold);
  outline-offset: 14px;
  margin: calc(var(--space-2) + 18px) 0 var(--space-2);
}
.needs-content::before{
  content: "PLACEHOLDER — REPLACE BEFORE LAUNCH" " · " attr(data-note);
  position: absolute;
  top: -16px; left: 0;
  transform: translateY(-100%);
  max-width: 100%;
  font-family: var(--font-body);
  font-size: 0.66rem; font-weight: 800; letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink); background: var(--gold);
  padding: 0.3rem 0.6rem; border-radius: 2px;
}
@media print{
  .needs-content{ outline: none; margin: 0; }
  .needs-content::before{ display: none; }
}

/* ---------- Responsive ---------- */
@media (max-width: 860px){
  .primary-nav{
    position: fixed; inset: 64px 0 0 0; background: var(--bg);
    flex-direction: column; align-items: flex-start; padding: var(--space-4) var(--space-3);
    transform: translateX(100%); transition: transform .3s var(--ease);
    border-top: 1px solid var(--border); gap: var(--space-3);
  }
  .primary-nav.is-open{ transform: translateX(0); }
  .nav-toggle{ display: flex; }
  .nav-cta{ order: 99; }

  .contact-grid{ grid-template-columns: minmax(0,1fr); }
  .quote-strip{ grid-template-columns: 1fr; }
  .gallery{ grid-template-columns: repeat(2, 1fr); }
  .board-row{ grid-template-columns: 1fr; gap: 0.35rem; }
  .board-head{ display: none; }
  /* Stacked layout: the photo becomes a banner above each program rather
     than a 92px thumbnail, and 16:9 keeps it from eating the whole screen. */
  .board-thumb{ margin-bottom: 0.6rem; }
  .board-thumb img{ aspect-ratio: 16 / 9; }
  .roster-row{ flex-direction: column; gap: var(--space-2); }
  .avatar-photo img{ width: 8rem; height: 8rem; }
  .roster-body p{ max-width: none; }
  .board-row:not(.board-head) [data-label]::before{
    content: attr(data-label) ": "; font-weight: 700; color: var(--text);
  }
  .taegeuk{ opacity: 0.35; width: 70vw; height: 70vw; right: -20%; }
  .hero{ min-height: auto; padding-top: var(--space-6); }

  /* Tighter offset so the dashed frame can't push the page into
     horizontal scroll on a phone, and let the long note wrap. */
  .needs-content{ outline-offset: 8px; margin-top: calc(var(--space-3) + 24px); }
  .needs-content::before{
    top: -10px; letter-spacing: 0.06em; white-space: normal; line-height: 1.35;
  }
}

/* On a narrow phone the two-up name row leaves ~108px per field once the card
   padding and gap are taken out, which is too tight to read what you typed.
   Stack them and reclaim the card padding. */
@media (max-width: 480px){
  .trial-form{ padding: var(--space-3); }
  .form-row-split{ grid-template-columns: minmax(0,1fr); gap: var(--space-2); }
}

/* Schedule row labels carry a belt/age qualifier under the class name. */
.schedule-table .row-note{
  display: block; font-family: var(--font-body); font-weight: 500;
  font-size: 0.72rem; text-transform: none; letter-spacing: 0;
  color: var(--text-muted); margin-top: 0.15rem;
}
.schedule-note{ margin-top: var(--space-2); font-size: 0.88rem; color: var(--text-muted); }

/* ---------- Belt ranks ---------- */
.rank-group{ margin-bottom: var(--space-4); }
.rank-title{
  font-size: var(--fs-h3); margin-bottom: var(--space-2);
  display: flex; align-items: baseline; gap: 0.6rem; flex-wrap: wrap;
}
.rank-title span{
  font-family: var(--font-body); font-size: 0.78rem; font-weight: 600;
  text-transform: uppercase; letter-spacing: 0.08em; color: var(--text-muted);
}
.rank-list{ display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 0.6rem; }
.rank{ display: flex; align-items: center; gap: 0.6rem; }
.rank-belt{
  position: relative; flex: none; width: 46px; height: 26px; border-radius: 3px;
  border: 1px solid var(--border); display: flex; align-items: center; justify-content: center;
  font-size: 0.7rem; font-weight: 800; overflow: hidden;
}
/* The stripe a rank is actually named for — "White w/ Yellow Stripe". */
.rank-stripe{ position: absolute; right: 0; top: 0; bottom: 0; width: 11px; }
.rank-n{ position: relative; opacity: 0.55; }
.rank-name{ font-size: 0.86rem; line-height: 1.3; }
.rank-note{ font-size: 0.88rem; color: var(--text-muted); border-left: 3px solid var(--accent); padding-left: 0.8rem; }

/* ---------- Trial form (Spark) ---------- */
.trial-badge{
  display: inline-block; background: var(--accent); color: var(--on-accent);
  font-size: 0.72rem; font-weight: 800; text-transform: uppercase; letter-spacing: 0.1em;
  padding: 0.3rem 0.7rem; border-radius: var(--radius-pill); margin-bottom: 0.7rem;
}
.trial-h{ font-size: var(--fs-h3); margin-bottom: var(--space-3); }
.program-error{ margin-top: 0.5rem; font-size: 0.85rem; color: var(--accent); font-weight: 600; }
/* A black belt on a dark page needs an edge or it reads as empty space. */
.rank-belt{ box-shadow: inset 0 0 0 1px rgba(238,240,236,0.28); }
/* Four quotes of uneven length — auto-fit keeps them tidy at every width. */
.quote-strip-4{ grid-template-columns: repeat(auto-fit, minmax(230px, 1fr)); align-items: start; }
/* Four quotes of uneven length — auto-fit keeps them tidy at every width. */
.quote-strip-4{ grid-template-columns: repeat(auto-fit, minmax(230px, 1fr)); align-items: start; }

/* ---------- Legal pages ---------- */
.legal{ padding-top: var(--space-5); }
.legal-wrap{ max-width: 74ch; }
.legal h1{ font-size: clamp(1.9rem,1.5rem+1.6vw,2.6rem); margin-bottom: var(--space-4); }
.legal h2{
  font-size: 1.15rem; margin: var(--space-4) 0 var(--space-2);
  padding-top: var(--space-2); border-top: 1px solid var(--border);
}
.legal h3{ font-size: 1rem; margin: var(--space-3) 0 var(--space-1); color: var(--text-muted); }
.legal p{ margin-bottom: var(--space-2); }
.legal ul{ list-style: disc; padding-left: 1.3rem; margin-bottom: var(--space-2); }
.legal li{ margin-bottom: 0.35rem; }
.legal a{ text-decoration: underline; }
