/* ---------------------------------------------------------------------------
   Medjay Studio Site — the reusable stylesheet.
   Copyright © 2026 Karim Neaim (Medjay Digital Solutions). All rights reserved.
   ---------------------------------------------------------------------------
   ⭐⭐ EVERY COLOUR IS A TOKEN, so a client deployment is a palette swap in this
   :root block and nothing else. The defaults below are DELIBERATELY NEUTRAL —
   this is a master template, and a factory colour that looks like somebody's
   brand is how a factory tagline ended up as a client's homepage hero.

   ⭐ LOGICAL PROPERTIES THROUGHOUT (margin-inline, padding-inline, inset-inline)
   rather than left/right, so dir="rtl" flips the whole layout with no separate
   Arabic stylesheet to keep in step.
   --------------------------------------------------------------------------- */

:root {
  --ink: #1c1a19;
  --ink-soft: #5d5754;
  --paper: #ffffff;
  --wash: #f6f3f1;
  --line: #e3ddd9;
  --accent: #8a7350;
  --accent-ink: #ffffff;

  /* ⭐ The punch card is a real product a student carries, so its ground and its
     filled circles are per-studio and belong here as tokens — not as rules a
     deployment writes into brand.css. Default to the ordinary wash and accent. */
  --card-ground: var(--wash);
  --card-line: var(--line);
  --dot-fill: var(--accent);
  --good: #2f6b46;
  --bad: #a33a2c;

  --radius: 14px;
  --gap: 1.25rem;
  --measure: 68ch;
  --shell: 1140px;

  --font-display: "Tenor Sans", Georgia, "Times New Roman", serif;
  --font-text: "Inter", system-ui, -apple-system, "Segoe UI", sans-serif;
}

/* ⭐ Arabic wants a face that actually has the glyphs, and a little more line
   height — Arabic ascenders and descenders need the room. */
:root:lang(ar),
html[dir="rtl"] {
  --font-display: "Tenor Sans", "Noto Naskh Arabic", "Segoe UI", serif;
  --font-text: "Noto Naskh Arabic", "Segoe UI", system-ui, sans-serif;
}
html[dir="rtl"] body { line-height: 1.85; }

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

/* ---------------------------------------------------------------------------
   ⭐⭐ THE PETAL WASH — the studio's colour, bleeding in from the edges.
   ---------------------------------------------------------------------------
   Every page was white with white cards on it, which read as a wireframe rather
   than as a brand. This lays soft blotches of the wash colour along the edges,
   the way her printed cards run watercolour into the paper.

   ⛔ IT IS BUILT FROM THE TOKENS, so it is the CLIENT'S colour on a client's
   deployment and neutral in the master — no image, nothing to swap, and a studio
   that sets --wash to sea-green gets sea-green petals.
   ⚠️ fixed attachment so it does not scroll away on a long page, and behind
   everything (z-index -1) so no card, button or photograph sits on top of a
   gradient it did not ask for.
   ⚠️ It sits on a ::before rather than on `body` itself, because `body` is the
   flex/paint root and a background there fights the sticky header's own. */
body::before {
  content: ''; position: fixed; inset: 0; z-index: -1; pointer-events: none;
  background:
    radial-gradient(58% 40% at 0% 0%,
      color-mix(in srgb, var(--wash) 88%, transparent) 0%, transparent 68%),
    radial-gradient(46% 34% at 100% 6%,
      color-mix(in srgb, var(--wash) 72%, transparent) 0%, transparent 64%),
    radial-gradient(70% 44% at 106% 62%,
      color-mix(in srgb, var(--wash) 82%, transparent) 0%, transparent 70%),
    radial-gradient(64% 40% at -8% 96%,
      color-mix(in srgb, var(--wash) 78%, transparent) 0%, transparent 66%),
    radial-gradient(38% 26% at 26% 108%,
      color-mix(in srgb, var(--line) 55%, transparent) 0%, transparent 62%),
    var(--paper);
}

/* ⭐ The cards lift OFF the wash rather than sitting in it — a translucent white
   so the petal colour still reads underneath, with a hairline in the brand line
   colour instead of grey. */
.card, .punch, .product-shots .shot.main {
  background: color-mix(in srgb, var(--paper) 92%, transparent);
  backdrop-filter: blur(2px);
}

/* ⚠️ A section that already paints the wash would double it against the petals
   and go muddy; these become transparent and let the body wash show through. */
#hero:not(.has-hero), #making { background: transparent; }

body {
  margin: 0;
  font-family: var(--font-text);
  color: var(--ink);
  background: var(--paper);
  line-height: 1.65;
  -webkit-font-smoothing: antialiased;
}

h1, h2, h3 { font-family: var(--font-display); font-weight: 400; line-height: 1.2; }
h1 { font-size: clamp(2rem, 5vw, 3.1rem); margin: 0 0 .5rem; }
h2 { font-size: clamp(1.5rem, 3vw, 2.1rem); margin: 0 0 .75rem; }
h3 { font-size: 1.2rem; margin: 0 0 .35rem; }
p { margin: 0 0 .9rem; max-width: var(--measure); }

a { color: inherit; text-decoration-thickness: 1px; text-underline-offset: 3px; }
a:hover { color: var(--accent); }

.shell { max-width: var(--shell); margin-inline: auto; padding-inline: 1.25rem; }
.soft { color: var(--ink-soft); }
.lead { font-size: 1.1rem; color: var(--ink-soft); }

/* ------------------------------------------------------------------- header */
/* ⭐ The header freezes at the top. ⚠️ It is BOTH the max-width container and
   the sticky element, so the background has to be painted on it — a transparent
   sticky header shows the page sliding through it. */
/* ⭐ The header spans the FULL WIDTH and centres its contents to the shell.
   ⛔⛔ It used to carry `max-width: var(--shell)` itself, which was survivable
   until it went sticky — then it became a floating island with the page
   scrolling past on both sides of it. A sticky bar has to reach both edges.
   ⚠️ Padding rather than an inner wrapper, so the existing flex row is
   untouched: max() keeps the phone padding and centres on a wide screen. */
#site-header {
  display: flex; align-items: center; gap: var(--gap); flex-wrap: wrap;
  /* ⭐ SHORT. The mark overhangs it rather than stretching it. */
  padding-block: .5rem;
  /* ⛔ Must not clip, or the overhanging logo is simply cut off. */
  overflow: visible;
  padding-inline: max(1.25rem, calc((100% - var(--shell)) / 2 + 1.25rem));
  border-block-end: 1px solid var(--line);
  position: sticky; top: 0; z-index: 30;
  background: var(--paper);
}
.brand { text-decoration: none; display: flex; flex-direction: column; }
.brand-name { font-family: var(--font-display); font-size: 1.4rem; letter-spacing: .02em; }
.brand-tag { font-size: .8rem; color: var(--ink-soft); }
#site-nav { margin-inline-start: auto; display: flex; gap: 1rem; align-items: center; flex-wrap: wrap; }
#site-nav a { text-decoration: none; font-size: .95rem; }
#site-nav a[aria-current="page"] { color: var(--accent); text-decoration: underline; }

.lang { display: inline-flex; align-items: center; margin-inline-start: .5rem; }
.lang select {
  border: 1px solid var(--line); background: var(--paper); color: var(--ink);
  padding: .25rem 1.6rem .25rem .6rem; border-radius: 999px; font: inherit;
  font-size: .85rem; cursor: pointer;
  /* ⭐ A caret drawn in CSS, so the control looks like the rest of the header
     rather than like the operating system's idea of a dropdown. */
  appearance: none;
  background-image: linear-gradient(45deg, transparent 50%, var(--ink-soft) 50%),
    linear-gradient(135deg, var(--ink-soft) 50%, transparent 50%);
  background-position: calc(100% - 15px) 52%, calc(100% - 10px) 52%;
  background-size: 5px 5px, 5px 5px;
  background-repeat: no-repeat;
}
/* ⛔ An icon-only control still needs a NAME. This hides the word from sight
   and keeps it for a screen reader — never `display: none`, which removes it
   from the accessibility tree as well. */
.visually-hidden {
  position: absolute; inline-size: 1px; block-size: 1px; overflow: hidden;
  clip-path: inset(50%); white-space: nowrap;
}

.burger { display: none; }

/* --------------------------------------------------------------------- main */
main { display: block; }
/* ⚠️ Was clamp(2rem, 5vw, 3.5rem) — 7cm between blocks on a wide screen, which
   on a page of short sections reads as things that fell apart. */
section { padding-block: clamp(1.5rem, 3vw, 2.4rem); }
section > .shell > h2 { margin-block-end: .3rem; }
section > .shell > .lead { margin-block-end: 1.1rem; }
section > .shell > h2:first-child { margin-block-start: 0; }
#hero { padding-block: clamp(2.5rem, 7vw, 5rem); background: var(--wash); }
#hero .about { max-width: var(--measure); }
.hero-acts { display: flex; gap: .75rem; flex-wrap: wrap; margin-block-start: 1.25rem; }
#making { background: var(--wash); }

/* -------------------------------------------------------------------- cards */
.grid {
  display: grid; gap: var(--gap);
  grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
}
/* ⭐ ONE SPACING SCALE. Cards, buttons and grids were each picking their own
   padding, so a page of them had four different gutters and nothing lined up.
   .9rem inside a card, 1.25rem between them, and buttons sit on the bottom edge
   so cards of different text lengths still end together. */
.card {
  border: 1px solid var(--line); border-radius: var(--radius);
  padding: 1rem; background: var(--paper);
  display: flex; flex-direction: column; gap: .3rem;
  /* ⭐ The card clips its own corners, so a full-bleed image needs no radius of
     its own and cannot disagree with the card about the curve. */
  overflow: hidden;
}
.card > :last-child { margin-block-end: 0; }
.card p { margin-block-end: .35rem; }
.card .meta { font-size: .88rem; color: var(--ink-soft); margin: 0; }
.card .price { font-size: 1.15rem; margin: .2rem 0; }
.card .btn { margin-block-start: auto; align-self: flex-start; }

.btn {
  display: inline-block; border: 1px solid var(--ink); background: var(--ink);
  color: var(--paper); padding: .55rem 1.05rem; border-radius: 999px;
  text-decoration: none; font: inherit; font-size: .95rem; cursor: pointer;
}
.btn:hover { background: var(--accent); border-color: var(--accent); color: var(--accent-ink); }
.btn.ghost { background: none; color: var(--ink); }
.btn.ghost:hover { color: var(--accent); }
.btn.small { padding: .35rem .8rem; font-size: .85rem; }
/* ⛔ A section's closing button sat flush against the card grid above it —
   zero gap, so it read as stuck to the last card rather than as its own thing.
   Any .btn that directly follows a grid or a rail gets air. */
.grid + .btn, .rail + .btn, .sessions + .btn, .rail-hint + .btn,
.grid + p > .btn, .day + .btn { margin-block-start: 1.25rem; }
section > .shell > .btn { margin-block-start: 1.25rem; }
.btn:disabled { opacity: .55; cursor: progress; }
.btn.on { background: var(--accent); border-color: var(--accent); color: var(--accent-ink); }

/* ------------------------------------------------------------------ images
   ⭐ Every picture is object-fit: cover inside a fixed aspect box, so a portrait
   phone photograph and a landscape product shot sit in the same grid without
   either being squashed. The studio's originals are all portrait; the web will
   not be.                                                                     */
/* ⭐ A portrait sits in a portrait frame. Her team photographs are all taller
   than they are wide, and a 4:3 box crops five faces down to five foreheads. */

/* ⭐ A teacher card: face, name, the studio's own words for what they do, and
   their own link. ⚠️ The role can be two lines ("Founder & CEO" plus an
   instructor line) and the card must not jump when it is. */
.card.teacher { gap: .15rem; }
.card.teacher h3 { margin: .35rem 0 0; }
.card.teacher .role { font-size: .85rem; color: var(--ink-soft); margin: 0; }
.card.teacher .social {
  display: inline-flex; align-items: center; gap: .35rem;
  margin-block-start: .45rem; font-size: .82rem; text-decoration: none;
  color: var(--ink-soft);
}
.card.teacher .social:hover { color: var(--accent); }
.card.teacher .social svg { inline-size: 1rem; block-size: 1rem; }
.card.teacher .role { font-size: .85rem; color: var(--ink-soft); margin: 0; }
.members section { margin-block-end: 2rem; }
.mem-head { display: flex; align-items: baseline; gap: 1rem; flex-wrap: wrap; }
.mem-head h1 { margin-block-end: .5rem; }
.mem-head .signout { margin-inline-start: auto; }
.card.teacher h3 { margin-block-start: .2rem; }

/* ------------------------------------------------------------------- the rail
   ⭐ A CSS scroll rail, not a JavaScript carousel. It works before the script
   runs, it works with the script broken, a keyboard reaches it, a trackpad and
   a phone already know how to drive it, and there is no autoplay stealing the
   page from somebody reading.
   ⚠️ scroll-snap so it stops on a card rather than half of one.               */
.rail {
  display: grid; grid-auto-flow: column; grid-auto-columns: minmax(220px, 260px);
  gap: var(--gap); overflow-x: auto; overscroll-behavior-inline: contain;
  scroll-snap-type: inline mandatory;
  padding-block-end: .6rem;
  /* ⚠️ Room for the focus ring — a rail with hidden overflow clips it, and a
     keyboard user then cannot see where they are. */
  padding-inline: 2px;
}
.rail > .card { scroll-snap-align: start; }
.rail:focus-visible { outline: 2px solid var(--accent); outline-offset: 4px; }
.rail-hint { font-size: .82rem; margin-block-start: .2rem; }
/* ⚠️ RTL needs nothing: grid-auto-flow column follows the writing direction, so
   the rail scrolls right-to-left in Arabic on its own. */
@media (hover: hover) { .rail-hint { opacity: .75; } }

/* ---------------------------------------------------------------------- images
   ⭐⭐ THE PICTURE IS THE TOP OF THE CARD, not a photograph floating inside it.
   A grid of images sitting inside the card's padding reads as pictures in
   mounts; bled to the edges it reads as a product card.

   Three rules, in this order, because two earlier attempts got it wrong:
     1. EVERY .card-img is a cropped box of a known ratio.
     2. Only a DIRECT CHILD of the card bleeds. A product card nests .card-img
        inside .card-img-link, and a rule matching both widened the link to 258
        and then the image inside it to 290 — overflowing its own card.
     3. A nested image simply fills its link.
   ⚠️ `inline-size: auto` is not a fix for either: on a replaced element it means
   the image's INTRINSIC width, which rendered one at 915px.                   */
.card-img {
  display: block;
  inline-size: 100%;
  /* ⛔⛔ block-size: auto IS LOAD-BEARING. The width/height ATTRIBUTES on the
     <img> — added to stop the page jumping as photographs arrive — set a used
     height, and `aspect-ratio` only computes one when the height is auto. So a
     1200px-tall portrait rendered 1200px tall inside a 258px card. The
     attributes were making the layout worse in exactly the way they were added
     to prevent. */
  block-size: auto;
  aspect-ratio: 4 / 3;
  object-fit: cover;
  background: var(--wash);
  border-radius: 0;
}
.card-img-link { display: block; }

/* The bleed: one card padding out on each side, and the card clips the corners. */
.card > .card-img,
.card > .card-img-link {
  inline-size: calc(100% + 2rem);
  margin-inline: -1rem;
  margin-block-start: -1rem;
  margin-block-end: .7rem;
}

/* ⭐ A PRODUCT GRID IS SQUARE. Her catalogue is shot portrait and square —
   915x1200 is typical — and a 4:3 landscape box takes the top and bottom off
   every one of them, which is what "out of frame" looks like. */
.product-card .card-img { aspect-ratio: 1 / 1; }
/* ⭐ A portrait belongs in a portrait frame: a 4:3 box crops a team page down
   to foreheads. */
.card-img.portrait { aspect-ratio: 3 / 4; }

/* ⛔ A card with no photograph must still look deliberate — the studio has not
   photographed everything, and a grey placeholder box is a worse answer than
   simply not showing one. */
.card:not(.has-image) h3 { margin-block-start: 0; }

/* The hero photograph sits behind the words, dimmed just enough to keep the
   text legible over any part of it. ⚠️ A real <img>, so it has alt text and is
   visible to search — never a CSS background. */
#hero.has-hero { position: relative; overflow: hidden; }
#hero.has-hero .hero-video,
#hero.has-hero .hero-img {
  position: absolute; inset: 0;
  inline-size: 100%; block-size: 100%;
  object-fit: cover;
  z-index: 0;
}
#hero.has-hero::after {
  content: ''; position: absolute; inset: 0; z-index: 1;
  background: linear-gradient(100deg,
    color-mix(in srgb, var(--wash) 92%, transparent) 0%,
    color-mix(in srgb, var(--wash) 78%, transparent) 45%,
    color-mix(in srgb, var(--wash) 30%, transparent) 100%);
}
#hero.has-hero .shell { position: relative; z-index: 2; }
/* ⚠️ A hero that loops for ever is exactly what prefers-reduced-motion is for. */
@media (prefers-reduced-motion: reduce) {
  #hero.has-hero .hero-video { animation: none; }
}
#hero.has-hero .about, #hero.has-hero .lead { text-shadow: 0 1px 2px rgba(255,255,255,.55); }

/* ⭐⭐ THE LOGO HANGS BELOW THE BAR (Karim, 2026-08-30). Three times the size
   would otherwise make the sticky header 130px of every screen. So the bar stays
   SHORT and the mark overhangs it — the header keeps its height and the logo
   keeps its size, which is the only way to have both.
   ⚠️ The overhang needs three things together, and it silently fails without any
   one of them: the header must not clip (no overflow hidden), the mark must sit
   above what it overhangs (z-index), and it must not add its own height to the
   bar — hence the fixed block-size on the brand and absolute positioning. */
.brand-logo {
  block-size: 7.2rem; inline-size: auto; margin-inline-end: .7rem;
  position: absolute; inset-block-start: .2rem; inset-inline-start: 0;
  z-index: 2; pointer-events: none;
}
.brand {
  position: relative;
  /* Room for the overhanging mark, and the words start after it. */
  padding-inline-start: 6.6rem;
  min-block-size: 3rem;
}
@media (max-width: 720px) {
  .brand-logo { block-size: 4.6rem; }
  .brand { padding-inline-start: 4.2rem; }
}

/* ⭐ Beside the words in the footer, not above them. */
.foot-logo { block-size: 4.5rem; inline-size: auto; flex-shrink: 0; }
.foot-inner { display: flex; align-items: center; gap: 1rem; flex-wrap: wrap; }
.foot-words > p { margin-block-end: .2rem; }
.foot-words > p:last-child { margin-block-end: 0; }
/* ⛔ The logo sits BESIDE the words, and the words stay stacked. An earlier
   version flipped `.brand` to row without wrapping them, so the studio name and
   its tagline ran together into one string with no gap at all. */
.brand { flex-direction: row; align-items: center; gap: .7rem; }
.brand-text { display: flex; flex-direction: column; line-height: 1.25; }

/* The product page: one large shot, the rest in a strip beneath it. */
.product-shots { margin-block-end: 1.25rem; }
.shot {
  inline-size: 100%;
  block-size: auto; border-radius: var(--radius);
  object-fit: cover; background: var(--wash);
}
.shot.main { aspect-ratio: 4 / 3; }
.shot-strip {
  display: grid; gap: .6rem; margin-block-start: .6rem;
  grid-template-columns: repeat(auto-fill, minmax(110px, 1fr));
}
.shot-strip .shot { aspect-ratio: 1 / 1; }

/* The studio's own photography — portrait, so the gallery keeps that shape. */
.gallery {
  display: grid; gap: var(--gap); margin-block-start: 1.25rem;
  grid-template-columns: repeat(auto-fill, minmax(210px, 1fr));
}
.gallery-img {
  inline-size: 100%;
  block-size: auto; aspect-ratio: 3 / 4; object-fit: cover;
  border-radius: var(--radius); background: var(--wash);
}

/* ---------------------------------------------------------------- timetable
   ⭐ GROUPED BY DAY, at a READING WIDTH. Her real schedule is 33 classes a week,
   so a fortnight is 136 rows. Left at the shell's full width the time sat on one
   edge and "Book a place" on the other with a metre of nothing between them, and
   the eye cannot connect the two.                                             */
/* ⭐ Centred, not left-hugged. At the shell's full width the rows sat against
   the left edge with half a screen of nothing beside them. The heading is
   centred WITH them — a heading at the page edge over centred rows is worse
   than either alone. */
.sessions, .day-head { max-inline-size: 46rem; margin-inline: auto; }
#timetable > .shell { max-width: 46rem; }
.sessions { list-style: none; margin: 0; padding: 0; }

/* ⛔⛔ A DAY IS NOT A LANDING SECTION. dayGroup() renders a <section>, which
   picked up the global `section { padding-block: clamp(2rem, 5vw, 3.5rem) }` —
   seven centimetres of air between every day, on a page with 29 of them. */
.day { padding-block: 0; margin-block-end: 1.15rem; }
.day-head {
  font-family: var(--font-display); font-size: 1.05rem; margin: 0 0 .2rem;
  padding-block-end: .3rem; border-block-end: 2px solid var(--line);
  position: sticky; top: 4.4rem; z-index: 2; background: var(--paper);
}

.session {
  display: grid; align-items: center; gap: .4rem 1rem;
  grid-template-columns: 3.4rem 1fr auto;
  padding-block: .5rem; border-block-end: 1px solid var(--line);
}
.session:last-child { border-block-end: 0; }
.session .time { font-weight: 600; font-variant-numeric: tabular-nums; }
.session .what { display: flex; gap: .5rem; flex-wrap: wrap; align-items: baseline; min-width: 0; }
.session .prog { font-family: var(--font-display); font-size: 1.02rem; }
.session .who { font-size: .86rem; color: var(--ink-soft); }
/* ⭐ The level of THIS occurrence, not of the class. A student choosing a night
   needs to know it is Beginners before she books, not when she arrives. */
.session .lvl {
  font-size: .68rem; letter-spacing: .05em; text-transform: uppercase;
  padding: .1rem .45rem; border-radius: 999px;
  background: var(--wash); color: var(--ink-soft); white-space: nowrap;
}
.session .act { display: flex; gap: .8rem; align-items: center; justify-self: end; }
.session .left { font-size: .84rem; color: var(--ink-soft); white-space: nowrap; }
/* ⛔ A full class is dimmed, never hidden — it still offers the waitlist. */
.session.full { opacity: .72; }

/* ⚠️ On a phone the row stacks: three columns at 360px puts "Book a place" on
   two lines inside a 60px box. */
@media (max-width: 620px) {
  .session { grid-template-columns: 3.2rem 1fr; }
  .session .act { grid-column: 1 / -1; justify-self: stretch; justify-content: space-between; }
  .day-head { top: 3.8rem; }
}

/* -------------------------------------------------------------- availability */
.avail { font-size: .9rem; margin: .15rem 0; }
.avail.yes { color: var(--good); }
.avail.no { color: var(--bad); }
.rating { font-size: .95rem; }
.rating-none { font-size: .85rem; }
.price.big { font-size: 1.6rem; font-family: var(--font-display); }

/* --------------------------------------------------------------- the card
   ⭐ The circles are the point — the satisfaction of a filling card is why
   punch cards work, and it is free retention. Filled in the brand accent, on
   the pale ground, exactly as the printed cards are.                        */
.punch {
  border: 1px solid var(--card-line); border-radius: var(--radius);
  padding: 1rem; margin-block-end: .8rem; background: var(--card-ground);
  display: flex; flex-wrap: wrap; gap: .6rem; align-items: center;
}
.punch .type { font-family: var(--font-display); font-size: 1.05rem; }
.dots { display: flex; gap: .4rem; flex-wrap: wrap; }
.dot {
  inline-size: 1.15rem; block-size: 1.15rem; border-radius: 50%;
  border: 1.5px solid var(--accent); display: inline-block;
}
.dot.filled { background: var(--dot-fill); border-color: var(--dot-fill); }
/* ⛔ An overdrawn card shows MORE stamps than circles rather than hiding them —
   the studio has to be able to see it happened. */
.dot.over { border-style: dashed; background: var(--bad); border-color: var(--bad); }
.punch .adj { inline-size: 100%; font-size: .82rem; }
.card-lookup { max-width: 34rem; }

/* -------------------------------------------------------------------- forms */
label { display: block; margin-block-end: .8rem; font-size: .9rem; color: var(--ink-soft); }
input, select, textarea {
  display: block; inline-size: 100%; margin-block-start: .3rem;
  padding: .6rem .7rem; border: 1px solid var(--line); border-radius: 10px;
  font: inherit; color: var(--ink); background: var(--paper);
  /* ⚠️ 16px minimum, or iOS zooms the whole page the moment a field is tapped. */
  font-size: 16px;
}
input:focus, select:focus, textarea:focus { outline: 2px solid var(--accent); outline-offset: 1px; }
form.enquiry { max-width: 34rem; margin-block-start: 1.5rem; }
.result { min-block-size: 1.4rem; font-size: .92rem; }
.result.good { color: var(--good); }
.result.bad { color: var(--bad); }
.note { padding: .9rem 1rem; border-radius: var(--radius); background: var(--wash); }
.note.bad { color: var(--bad); border: 1px solid var(--bad); }

.contact { display: grid; gap: var(--gap); grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); }

/* -------------------------------------------------------------------- modal */
.modal {
  position: fixed; inset: 0; background: rgba(28, 26, 25, .55);
  display: flex; align-items: center; justify-content: center; padding: 1rem; z-index: 50;
}
.modal-box {
  background: var(--paper); border-radius: var(--radius); padding: 1.5rem;
  max-inline-size: 26rem; inline-size: 100%; position: relative;
  max-block-size: 90vh; overflow-y: auto;
}
.modal-close {
  position: absolute; inset-block-start: .5rem; inset-inline-end: .6rem;
  border: none; background: none; font-size: 1.6rem; line-height: 1; cursor: pointer;
}
.choices { display: flex; gap: .5rem; flex-wrap: wrap; margin-block-end: .8rem; }

/* ------------------------------------------------------------------- footer */
#site-footer { border-block-start: 1px solid var(--line); margin-block-start: 2rem; background: var(--wash); }
.foot-inner { max-width: var(--shell); margin-inline: auto; padding: 2rem 1.25rem; }
.foot-name { font-family: var(--font-display); font-size: 1.2rem; margin-block-end: .3rem; }
.foot-bits { font-size: .9rem; color: var(--ink-soft); }
/* ⭐ Host's footer nav: the studio's own pages and Terms, one row, wrapping. */
.foot-links { display: flex; gap: 1rem; flex-wrap: wrap; font-size: .9rem; margin-block: .4rem; }
.foot-links a[aria-current="page"] { color: var(--accent); }
/* ⭐ The social badges — the team card's badge, in a row. */
.foot-social { display: flex; gap: .6rem; margin-block: .4rem .6rem; }
.foot-social .social { display: inline-flex; align-items: center; color: var(--ink-soft); }
.foot-social .social:hover { color: var(--accent); }
.foot-social .social svg { inline-size: 1.25rem; block-size: 1.25rem; }
.foot-fine { font-size: .8rem; color: var(--ink-soft); margin: 0; }

/* -------------------------------------------------------------------- phone */
@media (max-width: 760px) {
  .burger {
    display: inline-block; margin-inline-start: auto;
    border: 1px solid var(--line); background: none; border-radius: 999px;
    padding: .35rem .85rem; font: inherit; font-size: .9rem; cursor: pointer;
  }
  #site-nav { display: none; inline-size: 100%; flex-direction: column; align-items: flex-start; }
  #site-header.open #site-nav { display: flex; }
  .session { align-items: flex-start; }
  .session .act { margin-inline-start: 0; inline-size: 100%; justify-content: space-between; }
}

@media (prefers-reduced-motion: no-preference) {
  .btn { transition: background .15s ease, color .15s ease, border-color .15s ease; }
}

/* --------------------------------------------------------------- the basket */
/* ⭐ The count is part of the link, not beside it — a badge positioned over a
   nav item lands somewhere different in Arabic, where the whole bar mirrors. */
#site-nav a.cart-link { display: inline-flex; align-items: center; gap: .3rem; }
/* ⭐ currentColor, so the basket inherits the nav's colour and its hover
   without a second rule to keep in step. */
.cart-link .i {
  inline-size: 1.15rem; block-size: 1.15rem; fill: none; stroke: currentColor;
  stroke-width: 1.6; stroke-linecap: round; stroke-linejoin: round;
}
.cart-count {
  min-inline-size: 1.35rem; padding: 0 .35rem; border-radius: 999px;
  background: var(--accent); color: var(--accent-ink);
  font-size: .72rem; line-height: 1.35rem; text-align: center; font-weight: 600;
}

.cart-lines { list-style: none; margin: 0 0 1.5rem; padding: 0; }
.cart-line {
  display: grid; gap: .35rem 1rem; align-items: center;
  grid-template-columns: 84px minmax(0, 1fr) auto auto;
  padding: 1rem 0; border-block-end: 1px solid var(--line);
}
.cart-img { display: block; grid-row: span 2; }
/* ⛔ block-size auto, or the intrinsic height attribute on the <img> wins and
   the row grows to the full height of the photograph. Learned the hard way on
   the product grid; the same rule applies here. */
.cart-line .card-img {
  inline-size: 84px; block-size: auto; aspect-ratio: 1 / 1;
  object-fit: cover; border-radius: calc(var(--radius) - 6px);
}
.cart-what { display: flex; flex-direction: column; gap: .15rem; min-inline-size: 0; }
.cart-what .soft { font-size: .85rem; }
.cart-qty { display: flex; align-items: center; gap: .4rem; font-size: .85rem; color: var(--ink-soft); }
.cart-qty input { inline-size: 4.2rem; }
.cart-price { font-weight: 600; white-space: nowrap; }
.link-btn {
  background: none; border: 0; padding: 0; color: var(--ink-soft);
  font: inherit; font-size: .85rem; text-decoration: underline; cursor: pointer;
}
.link-btn:hover { color: var(--bad, #a33); }
.cart-total {
  display: flex; justify-content: space-between; align-items: baseline;
  gap: 1rem; font-size: 1.15rem; padding-block: .5rem;
  border-block-start: 2px solid var(--ink);
}

/* The buy box on a product page — the only place a required choice is asked. */
.product .buy {
  display: flex; flex-wrap: wrap; gap: .75rem 1rem; align-items: flex-end;
  margin: 1.25rem 0; padding: 1rem; border: 1px solid var(--line);
  border-radius: var(--radius); background: var(--wash);
}
.product .buy label { display: flex; flex-direction: column; gap: .25rem; font-size: .85rem; }
.product .buy input[name="qty"] { inline-size: 5rem; }
.btn.added { background: var(--good, #3a6b46); }

.checkout { display: grid; gap: .75rem; max-inline-size: var(--measure); }
.member-box { border: 1px solid var(--line); border-radius: var(--radius); padding: .75rem 1rem; }
.member-box summary { cursor: pointer; font-weight: 600; }
.member-box label { display: block; margin-block-start: .5rem; }
.placed .big { font-size: 1.1rem; }
.pay-note { white-space: pre-wrap; padding: 1rem; border: 1px solid var(--line);
  border-radius: var(--radius); background: var(--wash); }

@media (max-width: 620px) {
  .cart-line { grid-template-columns: 64px minmax(0, 1fr) auto; }
  .cart-line .card-img { inline-size: 64px; }
  .cart-price { grid-column: 2 / -1; }
}

/* ⛔⛔ A `display:` RULE BEATS THE BROWSER'S OWN `[hidden] { display: none }`.
   The guardian block and the one-time-code box are both `display: grid`, so
   `el.hidden = true` set the attribute, changed nothing, and every adult was
   asked for a parent's details while the code box sat there before any code had
   been sent. Nothing threw and the markup was correct — only looking found it.
   ⭐ One global rule, so no future component has to remember. */
[hidden] { display: none !important; }

/* ------------------------------------------------------ the members' door */
.door { max-inline-size: var(--measure); }
.tabs { display: flex; gap: .25rem; margin: 1rem 0 1.25rem; border-block-end: 1px solid var(--line); }
.tab {
  background: none; border: 0; border-block-end: 2px solid transparent;
  padding: .6rem .9rem; font: inherit; color: var(--ink-soft); cursor: pointer;
}
.tab.on { color: var(--ink); border-block-end-color: var(--accent); font-weight: 600; }
.door-form { display: grid; gap: .85rem; }
.door-form label { display: flex; flex-direction: column; gap: .25rem; }
.door-form label .soft { font-size: .8rem; }
/* ⭐ The guardian block reads as a block, so it is obvious the questions
   changed rather than that three fields quietly appeared. */
.guardian-fields { display: grid; gap: .85rem; padding: 1rem;
  border: 1px solid var(--line); border-radius: var(--radius); background: var(--wash); }
.code-step { display: grid; gap: .6rem; padding: 1rem; border: 1px dashed var(--accent);
  border-radius: var(--radius); }
.code-step input { font-size: 1.4rem; letter-spacing: .3em; text-align: center; }
.old-way { border-block-start: 1px solid var(--line); padding-block-start: .85rem; }
.old-way summary { cursor: pointer; color: var(--ink-soft); font-size: .9rem; }
.old-way label { display: flex; flex-direction: column; gap: .25rem; margin-block-start: .6rem; }
.who { display: flex; align-items: center; gap: .5rem; font-size: .9rem; color: var(--ink-soft); }

/* ------------------------------------------------------- buying a package */
.buy-form { display: grid; gap: .75rem; max-inline-size: var(--measure);
  margin-block-start: 1.5rem; padding: 1.25rem; border: 1px solid var(--line);
  border-radius: var(--radius); background: var(--wash); }
.buy-form label { display: flex; flex-direction: column; gap: .25rem; }
.pack-out:empty { display: none; }

/* ⭐ The making story leads the Equipment page — for a studio that builds its
   own rigs it is the difference, not a footnote. */
.making-lead { margin-block-end: 2rem; }
.making-lead h2 { margin-block-end: .5rem; }
.making-lead p { max-inline-size: var(--measure); }
.making-lead .gallery { margin-block-start: 1rem; }
/* ⭐ Short language codes need a narrower control than full names did. */
.lang select { padding-inline: .55rem 1.4rem; font-variant-caps: all-small-caps;
  letter-spacing: .04em; }

/* ---------------------------------------------------------------------------
   The waiver, on a member's own page
   ---------------------------------------------------------------------------
   ⛔ These classes were used in app.js markup before they were DEFINED. A class
   name is a CLAIM that a rule exists, and an unmet one has already squashed a
   whole desk's tables once. prove-site asserts the pair now.
   ⭐ TOKENS ONLY — this is the master, so every value is a variable a studio's
   brand.css can move. A literal colour here is a factory colour on somebody's
   website. */
.waiver-ask {
  border: 1px solid var(--line);
  border-inline-start: 3px solid var(--accent);
  border-radius: 10px;
  padding: 14px 18px;
  background: var(--wash);
}
.waiver-ask h2 { margin-top: 0; }
/* ⭐ SCROLLS, never truncated. She is agreeing to a real risk of injury, so the
   whole text has to be reachable — a fade-out over clipped words is how somebody
   later says they never saw the clause. */
.waiver-body {
  max-height: 40vh;
  overflow-y: auto;
  border: 1px solid var(--line);
  border-radius: 8px;
  padding: 12px 14px;
  margin-bottom: 14px;
  background: var(--paper);
  font-size: 0.95rem;
  line-height: 1.6;
}

/* ---------------------------------------------------------------------------
   Her own history — what she has taken, and what she has paid
   ---------------------------------------------------------------------------
   ⛔ SEVEN of the eight classes used by this section had no rule when it was
   written. A class name is a CLAIM that a rule exists; unmet, the rows collapse
   into an unreadable run of text — the same failure that squished every table on
   the desk. prove-site asserts the pair for the waiver; the habit is the point.
   ⭐ TOKENS ONLY. A literal colour in the master is a factory colour on somebody
   else's website. */
.history-body { margin-top: 12px; }
.history-body h3 {
  margin: 18px 0 6px;
  font-size: 0.95rem;
  color: var(--ink-soft);
}
.hist { list-style: none; margin: 0; padding: 0; }
/* ⚠️ A GRID, so the date, the class and the money line up down the page. Three
   inline spans wrap into porridge on a phone the moment a class name is long. */
.hist-row {
  display: grid;
  grid-template-columns: minmax(7.5rem, auto) 1fr auto;
  gap: 4px 12px;
  align-items: baseline;
  padding: 8px 0;
  border-bottom: 1px solid var(--line);
}
.hist-row:last-child { border-bottom: 0; }
.hist-row .when { color: var(--ink-soft); font-size: 0.9rem; white-space: nowrap; }
.hist-row .how { text-align: end; white-space: nowrap; }
/* ⭐ The status reads at a glance and never relies on colour ALONE — the word is
   always there, because a colour is no use to somebody who cannot see it. */
.chip {
  display: inline-block;
  padding: 1px 8px;
  border-radius: 999px;
  border: 1px solid var(--line);
  font-size: 0.8rem;
  background: var(--wash);
}
.chip.arrived { border-color: var(--accent); }
.chip.no_show { border-color: var(--ink-soft); }
.chip.cancelled { color: var(--ink-soft); }

@media (max-width: 30rem) {
  /* Two lines instead of three columns: the money follows the class rather than
     being squeezed off the edge. */
  .hist-row { grid-template-columns: 1fr auto; }
  .hist-row .when { grid-column: 1 / -1; }
}
