/* src/components/jr/jr.css — the shared Schola Jr surface.
   Transcribed from Faith's SJ2 export (art-source/design-sj2-2026-09-12). Every value here is
   measured off one of her screens; nothing is invented and nothing is rounded. Her screens
   carry their geometry inline, so the transcription moves each declaration into a class of the
   same name and the pixels stay identical (plan §Screen module contract).

   WHAT IS DELIBERATELY DIFFERENT FROM HER EXPORT, and only this:
     - Entrance keyframes are TRANSFORM-ONLY. Her sj2-rise and sj2-pop fade opacity; a
       hidden-tab render stalls an opacity animation and leaves whole pages invisible, which is
       a bug this repo has actually shipped (CLAUDE.md; plan ruling 3). The movement is hers,
       to the pixel; the fade is dropped. Written down in tools/audit/rules_audit.mjs, not silent.
     - Nothing loads from the network. Her @font-face block points at Google; this page loads
       assets/fonts/fonts.css instead.

   HER RULES THAT OUTRANK THE HOUSE STYLE (plan ruling 1, each one named in the auditor):
     - 44px chrome targets and 18px button radii. The house floor is 64px and a pill. SJ2 is a
       different, tighter design system and her frames win on pixels.
     - The star glyph "★" and the tick "✓" are drawn as text on her cards.
*/

/* ---------------------------------------------------------------- tokens */
:root {
  /* ink */
  --sj-ink: #13251f;
  --sj-ink-soft: #42544c;
  --sj-ink-body: #2c3d36;
  /* surfaces */
  --sj-page: #f4efe4;
  --sj-stage: #fff9e9;
  --sj-card: #fffdf6;
  --sj-line: #eadfc9;
  --sj-line-warm: #e2d8c5;
  --sj-sand: #eadfc9;
  /* the five accents her screens use */
  --sj-teal: #42a9c8;
  --sj-teal-ink: #19776f;
  --sj-teal-tint: #e3f5f8;
  --sj-teal-line: #cfe8e8;
  --sj-green: #439b4d;
  --sj-green-ink: #246c3c;
  --sj-green-tint: #e8f5d9;
  --sj-green-line: #bfe2cd;
  --sj-sky: #3f8fd2;
  --sj-sky-ink: #176c80;
  --sj-sky-tint: #e9f4fc;
  --sj-sky-line: #bfdcf3;
  --sj-sun: #f6bd2f;
  --sj-sun-ink: #b26f0a;
  --sj-sun-tint: #fff0b5;
  --sj-sun-line: #f0dcac;
  --sj-orange: #f36b35;
  --sj-orange-deep: #c84a22;
  /* radii, as she draws them */
  --sj-r-pill: 999px;
  --sj-r-cta: 14px;
  --sj-r-card: 18px;
  --sj-r-panel: 24px;
  --sj-r-hero: 28px;
  --sj-r-stage: 26px;
  /* chrome */
  --sj-chrome-h: 76px;
  --sj-nav-h: 72px;
  --sj-font: 'Quicksand', system-ui, sans-serif;
  /* Andika is the story face. Until assets/fonts/andika-*.woff2 land (plan phase 1b) this
     stack simply resolves to Quicksand, which is a legibility difference on reading text and
     nothing else. It is NOT a placeholder: no glyph is invented, the words are the words. */
  --sj-font-story: 'Andika', 'Quicksand', system-ui, sans-serif;
}

/* ---------------------------------------------------------------- the stage */
.jr-body {
  margin: 0;
  background: var(--sj-page);
  font-family: var(--sj-font);
  color: var(--sj-ink);
  -webkit-font-smoothing: antialiased;
}

.jr-root {
  position: fixed;
  inset: 0;
  overflow: hidden;
  background: var(--sj-page);
  font-family: var(--sj-font);
}

.jr-fit { position: absolute; inset: 0; }

/* Her tablet stage: a fixed 1440x940, centred, scaled to the bezel by jr_app.js.
   transform-only, up to 2x on a big desktop window (the fit lives in the shell, not here). */
.jr-stage {
  position: absolute;
  left: 50%;
  top: 50%;
  width: 1440px;
  height: 940px;
  transform: translate(-50%, -50%);
  transform-origin: center center;
  overflow: hidden;
  background: var(--sj-stage);
}

.jr-screen { position: absolute; inset: 0; }

/* ---------------------------------------------------------------- the note toast */
/* Her shell's PENDING note: bottom 96px, centred, 3.2 seconds. */
.jr-note-rail {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 96px;
  z-index: 40;
  display: flex;
  justify-content: center;
  pointer-events: none;
}

.jr-note {
  display: flex;
  align-items: center;
  gap: 11px;
  max-width: 720px;
  padding: 13px 22px 13px 16px;
  border-radius: var(--sj-r-pill);
  background: var(--sj-ink);
  color: var(--sj-card);
  box-shadow: 0 12px 30px rgba(35, 50, 44, .34);
  font-family: var(--sj-font);
  font-weight: 600;
  font-size: 17px;
  text-wrap: pretty;
}

.jr-note-dot {
  flex: none;
  width: 26px;
  height: 26px;
  border-radius: 50%;
  background: var(--sj-teal);
  display: flex;
  align-items: center;
  justify-content: center;
  font-weight: 700;
  font-size: 15px;
}

/* ---------------------------------------------------------------- fail loud */
/* No fallback renderer (CLAUDE.md). An unbuilt route says which file has to exist. This is a
   developer surface: it appears only where a screen has not been ported, and it says so in
   plain English rather than drawing a grey box that looks finished. */
.jr-fail {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 14px;
  padding: 0 120px;
  text-align: center;
  background: var(--sj-stage);
}

.jr-fail-head { margin: 0; font-weight: 700; font-size: 30px; color: var(--sj-ink); }
.jr-fail-detail {
  margin: 0;
  max-width: 62ch;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 15px;
  line-height: 1.5;
  color: var(--sj-ink-soft);
  text-wrap: pretty;
}
.jr-fail-back {
  margin-top: 6px;
  font-weight: 600;
  font-size: 17px;
  color: var(--sj-teal-ink);
  text-decoration: underline;
  text-underline-offset: 4px;
}

/* ---------------------------------------------------------------- shared controls */

/* The one orange primary per screen. 56px tall, 14px radius, a 5px hard shadow that the
   press flattens. Her Today hero draws it; every screen reuses it. */
.jr-cta {
  flex: none;
  white-space: nowrap;
  appearance: none;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  min-height: 56px;
  padding: 0 26px;
  border: 1px solid var(--sj-orange-deep);
  border-radius: var(--sj-r-cta);
  color: #ffffff;
  background: var(--sj-orange);
  box-shadow: 0 5px 0 var(--sj-orange-deep);
  font-family: var(--sj-font);
  font-size: 19px;
  font-weight: 700;
  transition: transform 150ms ease, box-shadow 150ms ease, background 150ms ease;
}
.jr-cta:hover { background: #ef7149; transform: translateY(-1px); box-shadow: 0 7px 0 var(--sj-orange-deep); }
.jr-cta:active { transform: translateY(3px); box-shadow: 0 2px 0 var(--sj-orange-deep); }

/* Her Welcome card's tall CTA: 62px, an 18px radius and a second, softer shadow. */
.jr-cta-tall {
  position: relative;
  z-index: 2;
  flex: none;
  margin-top: 2px;
  box-sizing: border-box;
  min-height: 62px;
  padding: 0 22px;
  border: none;
  border-radius: var(--sj-r-card);
  background: var(--sj-orange);
  color: var(--sj-card);
  font-family: var(--sj-font);
  font-weight: 700;
  box-shadow: 0 5px 0 var(--sj-orange-deep), 0 10px 20px rgba(181, 69, 10, .18);
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 12px;
  cursor: pointer;
  text-decoration: none;
}
.jr-cta-tall:active { transform: translateY(5px); box-shadow: 0 0 0 var(--sj-orange-deep), 0 4px 10px rgba(181, 69, 10, .2); }

/* ---------------------------------------------------------------- animation */
/* TRANSFORM-ONLY. Her sj2-rise and sj2-pop each began at opacity 0; the movement below is hers
   unchanged and the fade is gone (plan ruling 3; CLAUDE.md hidden-tab rule). */
@keyframes sj2-rise {
  from { transform: translateY(16px); }
  to { transform: none; }
}

@keyframes sj2-pop {
  0% { transform: scale(.86); }
  64% { transform: scale(1.06); }
  100% { transform: scale(1); }
}

.jr-rise { animation: sj2-rise 400ms cubic-bezier(.2, .75, .25, 1) both; }
.jr-rise-quick { animation: sj2-rise 260ms cubic-bezier(.2, .75, .25, 1) both; }
.jr-pop { animation: sj2-pop 320ms cubic-bezier(.2, .75, .25, 1) both; }

/* Her own reduced-motion block, kept: on this side of the app it stops every animation.
   REDUCED MOTION IS NOT REDUCED SOUND — the cues in src/shell/jr_sound.js are untouched by it. */
@media (prefers-reduced-motion: reduce) {
  .jr-root *,
  .jr-root *::before,
  .jr-root *::after {
    animation: none !important;
    transition-duration: 200ms !important;
  }
}

/* ---------------------------------------------------------------- a11y */
.jr-sr {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
}

/* ------------------------------------------------- her Sept 6 supporting-elements art */
/* One rule for every picture out of ScholaJr_Supporting_Elements/, in the slots her own map
   names (DECISIONS #109). CONTAIN, not cover: the art is square, these slots are not, and her
   pack says not to stretch it. No shadow either: the PNGs carry their own contact shading.
   See packArt() in jr.js. */
.jr-pack-art {
  position: absolute;
  inset: 0;
  display: block;
  background-repeat: no-repeat;
  background-size: contain;
  background-position: center;
}

/* ---------------------------------------------------------------- her dashed capsule */
/* The <image-slot> empty state out of her export, minus the authoring chrome: a translucent
   frame, a 1.5px dashed ring at .35, and the caption naming the picture. See dropSlot() in
   jr.js for why this is allowed to exist where art does not. */
.jr-slot {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 12px;
  box-sizing: border-box;
  text-align: center;
  background: rgba(127, 127, 127, .08);
  color: var(--sj-ink);
  overflow: hidden;
}

.jr-slot::after {
  content: '';
  position: absolute;
  inset: 0;
  pointer-events: none;
  border: 1.5px dashed currentColor;
  opacity: .35;
}

.jr-slot-cap {
  max-width: 90%;
  font: 500 13px/1.3 var(--sj-font);
  letter-spacing: .01em;
  opacity: .75;
  text-wrap: pretty;
}

/* ================================================================ phones (DECISIONS #164)
   Faith, 2026-09-14: "now make it work well on phones too".

   Two states, and only these. Neither redraws a screen of hers.

   1. `.jr-phone-natural` — a GROWN-UP route on a phone. The stage stops being a fixed,
      transform-scaled 1440x940 box and becomes the page: static flow, the phone's own width,
      the document scrolling the way a phone scrolls. The screen modules are untouched; only
      the box they sit in changes, which is why a rotation keeps a half-typed code. The class
      is set by src/shell/jr_app.js, never by a media query alone: the same 760px width happens
      on a small laptop, where the stage IS still 1440 wide and a phone layout would be a lie
      (the reason grownups.css dropped her media rules in the first place).

   2. `.jr-portrait` — a CHILD route on a phone held upright. One card, in her tokens, on top
      of the stage. The screen underneath stays mounted and keeps its state.

   Safe areas are paid out here rather than inside a screen, because the insets belong to the
   device and the screens belong to her. */

.jr-body-natural {
  overflow: auto;
  background: var(--sj-page);
  overscroll-behavior-y: none;
}

.jr-root.jr-phone-natural {
  position: static;
  inset: auto;
  overflow: visible;
  min-height: 100vh;
  min-height: 100dvh;
  padding-left: env(safe-area-inset-left);
  padding-right: env(safe-area-inset-right);
}

.jr-root.jr-phone-natural .jr-fit { position: static; inset: auto; }

.jr-root.jr-phone-natural .jr-stage {
  position: static;
  left: auto;
  top: auto;
  width: auto;
  height: auto;
  min-height: 100vh;
  min-height: 100dvh;
  transform: none;
  overflow: visible;
  background: var(--sj-page);
}

/* The screen host becomes the page's own column. `position:relative` is load-bearing: two of
   her grown-up screens (Sites, Browser) build their chrome as absolutely positioned layers,
   and out here they have to keep resolving against the screen and not against the viewport. */
.jr-root.jr-phone-natural .jr-screen {
  position: relative;
  inset: auto;
  display: flex;
  flex-direction: column;
  min-height: 100vh;
  min-height: 100dvh;
}

/* Every grown-up screen root is `position:absolute; inset:0` inside her stage. Out here that
   would collapse to nothing, so the six of them flow instead. Their own phone stacking is in
   each screen's stylesheet; this is the box, not the layout. */
.jr-root.jr-phone-natural .jr-gu,
.jr-root.jr-phone-natural .jr-gate,
.jr-root.jr-phone-natural .jr-setup,
.jr-root.jr-phone-natural .jr-add,
.jr-root.jr-phone-natural .jr-read {
  position: static;
  inset: auto;
  min-height: 100vh;
  min-height: 100dvh;
}

/* The note toast is bottom:96px of a 940px stage. On the page it is a real fixed pill. */
.jr-root.jr-phone-natural .jr-note-rail {
  position: fixed;
  bottom: calc(16px + env(safe-area-inset-bottom));
  padding: 0 12px;
}

/* ---------------------------------------------------------------- the portrait card */
/* Her stage stays underneath, still scaled to fit and still pinch-zoomable; this sits on it. */
.jr-portrait {
  position: fixed;
  inset: 0;
  z-index: 60;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: calc(20px + env(safe-area-inset-top)) 20px calc(20px + env(safe-area-inset-bottom));
  background: rgba(244, 239, 228, .94);
}

.jr-portrait-card {
  width: 100%;
  max-width: 340px;
  box-sizing: border-box;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 18px;
  padding: 28px 22px 24px;
  border-radius: var(--sj-r-panel);
  background: var(--sj-card);
  border: 2px solid var(--sj-teal-line);
  box-shadow: 0 18px 44px rgba(22, 53, 43, .16);
  text-align: center;
}

/* Not a picture and not a glyph she drew: a turned rectangle, the shape of the ask. */
.jr-portrait-glyph {
  width: 52px;
  height: 76px;
  border-radius: 12px;
  border: 3px solid var(--sj-teal);
  transform: rotate(-28deg);
}

.jr-portrait-line {
  margin: 0;
  font-family: var(--sj-font);
  font-weight: 600;
  font-size: 20px;
  line-height: 1.35;
  color: var(--sj-ink);
  text-wrap: pretty;
}

.jr-portrait-go {
  min-height: 64px;
  min-width: 180px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0 26px;
  border-radius: var(--sj-r-pill);
  background: var(--sj-teal);
  color: #fffdf6;
  font-family: var(--sj-font);
  font-weight: 700;
  font-size: 18px;
  text-decoration: none;
}
