/* ==========================================================================
   SpeakUp Too  -  Sensory App House Ltd
   Palette taken from the app icon: cyan trace on near-black.
   ========================================================================== */

:root{
  --ink:        #06090C;
  --surface:    #101820;
  --surface-2:  #18242E;
  --line:       #24343F;
  --cyan:       #35E0F2;
  --cyan-deep:  #0A6C7A;
  --amber:      #F5A524;
  --text:       #E8F4F8;
  --text-dim:   #8FA3AD;

  --chip: clamp(44px, 7.5vmin, 76px);
  --pad:  clamp(12px, 2.2vmin, 24px);

  --ui: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
}

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

html, body{
  margin:0; padding:0;
  height:100%;
  background: var(--ink);
  color: var(--text);
  font-family: var(--ui);
  overflow: hidden;
  overscroll-behavior: none;
  -webkit-text-size-adjust: 100%;
  -webkit-tap-highlight-color: transparent;
  touch-action: manipulation;
}

body{ user-select: none; -webkit-user-select: none; }

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

:where(button, input, [tabindex]):focus-visible{
  outline: 3px solid var(--cyan);
  outline-offset: 3px;
}

/* ==========================================================================
   MENU
   ========================================================================== */

/* The splash artwork carries the wordmark and eight glowing slots. Rather
   than stretch it to the viewport, it sits on a board held at its own
   1500 x 952 aspect ratio and scaled to fit, so the artwork is never
   distorted and the letterbox picks up the green of its own edge. The tile
   grid is measured from the painted slots: they start at 16.53% / 20.01%
   and span 74.30% x 55.15% of the board. */
.menu{
  position: fixed; inset: 0;
  display: grid; place-items: center;
  /* Green sampled from the old iOS portrait build, so the letterbox and the
     portrait phone layout share the same backdrop as the original app. */
  background: linear-gradient(180deg, #2D504A 0%, #26493A 45%, #1F4124 100%);
}

/* Sized with min() on both axes rather than aspect-ratio alone. An
   aspect-ratio box with width:100% ignores max-height and spills off a short
   screen, which cropped the artwork on every phone held in landscape. */
.board{
  position: relative;
  width:  min(100vw, calc(100vh * 1500 / 952));
  height: min(100vh, calc(100vw * 952 / 1500));
  background: #0D1512 url(../images/splash.jpg) 0 0 / 100% 100% no-repeat;
}
@supports (height: 100dvh){
  .board{
    width:  min(100dvw, calc(100dvh * 1500 / 952));
    height: min(100dvh, calc(100dvw * 952 / 1500));
  }
}

/* Hidden by default: the wordmark is painted into the splash artwork. It
   only becomes visible in the portrait phone layout, where the artwork is
   set aside. */
.wordmark{
  position:absolute; width:1px; height:1px;
  margin:-1px; overflow:hidden; clip-path: inset(50%); white-space:nowrap;
}

.tiles{
  position: absolute;
  left: 16.53%; top: 20.01%;
  width: 74.30%; height: 55.15%;
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  grid-template-rows: repeat(2, 1fr);
  column-gap: 3.93%;
  row-gap: 23.81%;
}

.tile{
  appearance: none;
  min-width: 0; min-height: 0;
  padding: 0;
  border: none;
  border-radius: 2px;
  cursor: pointer;
  /* content-box origin keeps the white filling the whole tile while the
     artwork is inset, so the characters no longer touch the frame. */
  background: #FFFFFF var(--art) center / contain no-repeat;
  background-origin: content-box;
  padding: 7%;
  opacity: .7;
  transition: opacity .14s ease, transform .14s ease;
}
/* Declared here, not in the markup: a url() inside a custom property is
   resolved against the stylesheet that uses it, so an inline value would
   have been looked up under css/. */
.tile[data-mode="1"]{ --art: url(../images/1.png); }
.tile[data-mode="2"]{ --art: url(../images/2.png); }
.tile[data-mode="3"]{ --art: url(../images/3.png); }
.tile[data-mode="4"]{ --art: url(../images/4.png); }
.tile[data-mode="5"]{ --art: url(../images/5.png); }
.tile[data-mode="6"]{ --art: url(../images/6.png); }
.tile[data-mode="7"]{ --art: url(../images/7.png); }
.tile[data-mode="8"]{ --art: url(../images/8.png); }

.tile:hover, .tile:focus-visible{ opacity: 1; }
.tile:active{ transform: scale(.97); opacity: 1; }

/* ==========================================================================
   ACTIVITY STAGE
   ========================================================================== */

.stage{ position: fixed; inset: 0; background: #000; }

#scene{
  position:absolute; inset:0;
  width:100%; height:100%;
  display:block;
}

/* gauge.js writes canvas.style.width/height inline from the canvas
   attributes, which beats any width set here. The size is therefore worked
   out in sizeGauge() and the attributes are set before the Gauge is built;
   this rule only centres the result. */
#gauge{
  position:absolute;
  left:50%; top:50%;
  transform: translate(-50%, -50%);
  border-radius: 8px;
  box-shadow: 0 0 24px rgba(255,255,255,.65);
}

/* ==========================================================================
   FLOATING CHIPS
   ========================================================================== */

.chip{
  position: fixed;
  z-index: 40;
  width: var(--chip); height: var(--chip);
  border: none; border-radius: 50%;
  cursor: pointer;
  background: rgba(6,9,12,.55) center / 62% 62% no-repeat;
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  box-shadow: 0 2px 14px rgba(0,0,0,.5);
  transition: transform .14s ease, background-color .14s ease;
}
.chip:active{ transform: scale(.92); }

.chip--home{
  top: max(var(--pad), env(safe-area-inset-top));
  left: max(var(--pad), env(safe-area-inset-left));
  background-image: url(../images/home.png);
}
.chip--next{
  top: max(var(--pad), env(safe-area-inset-top));
  right: max(var(--pad), env(safe-area-inset-right));
  background-image: url(../images/plus.png);
}
/* The gear lives on the menu only, top right, where it has always been.
   During an activity the screen belongs to the child. */
.chip--setup{
  top: max(var(--pad), env(safe-area-inset-top));
  right: max(var(--pad), env(safe-area-inset-right));
  background-image: url(../images/settings.png);
}
body[data-view="stage"] .chip--setup{ display: none; }

/* Shown on the stage only when the microphone could not be started. */
.chip--micfail{
  bottom: max(var(--pad), env(safe-area-inset-bottom));
  right: max(var(--pad), env(safe-area-inset-right));
  display: grid; place-items: center;
  color: #FFD9D2;
  background-color: rgba(150, 32, 20, .85);
}
.chip--micfail svg{ width: 55%; height: 55%; }
.chip--micfail[hidden]{ display: none; }

/* ==========================================================================
   SETUP PANEL  -  the therapist's instrument
   ========================================================================== */

/* Deliberately transparent. The whole point of reaching the setup while an
   activity is running is to watch the shape respond as the marks move, so
   this only catches taps outside the panel. */
.scrim{
  position: fixed; inset:0; z-index: 50;
  background: transparent;
}

 /* A sheet rather than a full-height drawer: with two controls in it, a
    floor-to-ceiling panel is mostly empty. Height follows the content. */
.setup{
  position: fixed; z-index: 60;
  top: max(var(--pad), env(safe-area-inset-top));
  right: max(var(--pad), env(safe-area-inset-right));
  width: min(400px, calc(100vw - 2 * var(--pad)));
  max-height: calc(100% - 2 * var(--pad));
  display: flex; flex-direction: column;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 16px;
  box-shadow: 0 18px 50px rgba(0,0,0,.6);
  transform: translateX(calc(100% + var(--pad)));
  transition: transform .26s cubic-bezier(.22,.9,.3,1);
  overflow: hidden;
}
.setup[data-open="true"]{ transform: translateX(0); }

.setup__head{
  display:flex; align-items:center; justify-content:space-between;
  gap: 12px;
  padding: 14px 16px;
  border-bottom: 1px solid var(--line);
}
.setup__badge{
  width: 34px; height: 34px; flex: 0 0 auto;
  display:grid; place-items:center;
  border-radius: 9px;
  background: var(--surface-2);
  color: var(--cyan);
}
.setup__badge svg{ width: 20px; height: 20px; }

.setup__close{
  width: 34px; height: 34px; flex: 0 0 auto;
  border: 1px solid var(--line); border-radius: 9px;
  background: transparent; cursor: pointer;
  position: relative;
}
.setup__close::before, .setup__close::after{
  content:""; position:absolute; left:50%; top:50%;
  width: 15px; height: 2px; background: var(--text-dim);
}
.setup__close::before{ transform: translate(-50%,-50%) rotate(45deg); }
.setup__close::after { transform: translate(-50%,-50%) rotate(-45deg); }
.setup__close:hover::before, .setup__close:hover::after{ background: var(--text); }

.setup__body{
  flex:1; overflow-y:auto;
  padding: 18px;
  display:flex; flex-direction:column; gap: 18px;
}

/* --- controls kept for setup work but hidden in the shipped build.
       Flip ADVANCED in app.js to bring them back. --- */
body:not([data-advanced="true"]) .ctl--switch,
body:not([data-advanced="true"]) #btn-calibrate,
body:not([data-advanced="true"]) #btn-reset,
body:not([data-advanced="true"]) #btn-mic{ display: none; }

body:not([data-advanced="true"]) .setup__body{ gap: 12px; padding: 16px; }
body:not([data-advanced="true"]) .setup__actions{ display: none; }

/* --- the loudness scale --- */
.meter{
  background: var(--ink);
  border: 1px solid var(--line);
  border-radius: 12px;
  padding: 12px 14px 10px;
}
#meter{ display:block; width:100%; height:70px; }

.meter__read{
  display:flex; align-items:center; justify-content:center;
  margin: 6px 0 0;
}

/* Live preview: the disc grows exactly as the shape on screen does. */
.meter__preview{
  width: 62px; height: 62px; flex: 0 0 auto;
  display:grid; place-items:center;
  border-radius: 50%;
  background: var(--surface-2);
}
.meter__preview i{
  display:block;
  width: 56px; height: 56px;
  border-radius: 50%;
  background: var(--cyan);
  transform: scale(.12);
  transform-origin: center;
  will-change: transform;
}
/* --- slider rows: icon, track, number --- */
.ctl{
  display:grid;
  grid-template-columns: 30px 1fr;
  align-items:center;
  gap: 0 14px;
}
.ctl__icon{
  width: 26px; height: 26px;
  display:grid; place-items:center;
  color: var(--text-dim);
}
.ctl__icon svg{ width: 22px; height: 22px; }
.ctl__icon--min{ color: var(--cyan); }
.ctl__icon--max{ color: var(--amber); }

.ctl input[type=range]{ width:100%; margin:0; }

input[type=range]{
  appearance:none; -webkit-appearance:none;
  height: 34px; background: transparent; cursor: pointer;
}
input[type=range]::-webkit-slider-runnable-track{
  height: 6px; border-radius: 3px; background: var(--surface-2);
}
input[type=range]::-moz-range-track{
  height: 6px; border-radius: 3px; background: var(--surface-2);
}
input[type=range]::-webkit-slider-thumb{
  -webkit-appearance:none;
  width: 28px; height: 28px; margin-top: -11px;
  border-radius: 50%; border: 3px solid var(--ink);
  background: var(--cyan);
}
input[type=range]::-moz-range-thumb{
  width: 28px; height: 28px;
  border-radius: 50%; border: 3px solid var(--ink);
  background: var(--cyan);
}
#max-db::-webkit-slider-thumb{ background: var(--amber); }
#max-db::-moz-range-thumb{ background: var(--amber); }

/* --- switch row --- */
.ctl--switch{ grid-template-columns: 30px 1fr auto; }
.ctl--switch input[type=checkbox]{ grid-column: 3; }
input[type=checkbox][role=switch]{
  appearance:none; -webkit-appearance:none;
  width: 52px; height: 30px; border-radius: 15px;
  background: var(--surface-2); border: 1px solid var(--line);
  position: relative; cursor: pointer; margin:0;
  grid-column: 3;
  transition: background-color .16s ease;
}
input[type=checkbox][role=switch]::after{
  content:""; position:absolute; top: 3px; left: 3px;
  width: 22px; height: 22px; border-radius: 50%;
  background: var(--text-dim);
  transition: transform .16s ease, background-color .16s ease;
}
input[type=checkbox][role=switch]:checked{ background: var(--cyan-deep); }
input[type=checkbox][role=switch]:checked::after{
  transform: translateX(22px); background: var(--cyan);
}

/* --- icon buttons --- */
/* Anchored to the bottom so a tall panel does not end in a void. */
.setup__actions{ display:flex; gap: 10px; margin-top: auto; }
.act{
  flex: 1 1 0;
  height: 52px;
  display:grid; place-items:center;
  border-radius: 12px; cursor: pointer;
  border: 1px solid var(--line);
  background: var(--surface-2); color: var(--text);
  transition: background-color .14s ease, border-color .14s ease;
}
.act svg{ width: 24px; height: 24px; }
.act:hover{ border-color: var(--cyan-deep); }
.act--primary{
  background: var(--cyan); color: #04212A; border-color: var(--cyan);
  flex: 2 1 0;
}
.act--primary:hover{ background: #5BE9F7; }
.act[hidden]{ display:none; }

.setup__status{
  margin: 0; min-height: 1.2em;
  font-size: 13px; line-height:1.45; color: var(--text-dim);
}
.setup__status[data-tone="error"]{ color: #FF9B8A; }
.setup__status[data-tone="good"]{ color: var(--cyan); }

/* Short screens, mostly phones held in landscape. Everything must stay on
   one page: a therapist should never have to scroll to reach the buttons. */
@media (max-height: 520px){
  .setup__head{ padding: 10px 14px; }
  body:not([data-advanced="true"]) .setup__body{ gap: 6px; padding: 12px 14px; }
  .setup__body{ padding: 10px 14px; gap: 8px; }
  .meter{ padding: 8px 12px 6px; border-radius: 10px; }
  #meter{ height: 50px; }
  .meter__read{ margin-top: 2px; }
  .meter__preview{ width: 38px; height: 38px; }
  .meter__preview i{ width: 34px; height: 34px; }
  input[type=range]{ height: 28px; }
  .act{ height: 44px; }
  .setup__status{ min-height: 0; }
}

/* ==========================================================================
   PORTRAIT PHONE
   The splash artwork is a landscape painting with eight slots in it. Letterboxed
   into a tall, narrow screen it wastes half the height and leaves the tiles
   about 60 x 50 px. So on a phone held upright the artwork steps aside and the
   tiles take the whole screen in two columns.

   The gate is a width rather than an aspect ratio because it has to separate
   phones from tablets, and the two do not overlap on width: phones in portrait
   run 360 to 430 px, tablets 744 px and up. Tablets keep the painted board in
   both orientations, which is what Dave wanted  -  the artwork sits well at that
   size and carries the branding.
   ========================================================================== */
@media (orientation: portrait) and (max-width: 560px){
  /* Pinned rather than sized in percentages: the grid row is content-sized,
     so a percentage height on the board resolves cyclically and collapses. */
  .board{
    position: absolute; inset: 0;
    width: auto; height: auto;
    background-color: #26493A;
    background-image:
      radial-gradient(75% 20% at 50% 7%,
                      rgba(198, 216, 172, .34), rgba(198, 216, 172, 0) 72%),
      linear-gradient(180deg, #2D504A 0%, #26493A 45%, #1F4124 100%);
    display: flex; flex-direction: column;
    padding-top: max(14px, env(safe-area-inset-top));
    padding-right: 14px;
    padding-bottom: max(14px, env(safe-area-inset-bottom));
    padding-left: 14px;
    gap: 12px;
  }

  /* The wordmark is the artwork's own lettering, lifted glyph by glyph out of
     splash.jpg and set horizontally. Using the picture rather than a typeface
     keeps it identical to the painted version, needs no font download, and
     works offline. The text stays in the heading for screen readers. */
  .wordmark{
    position: static; width: auto;
    margin: 0; overflow: visible; clip-path: none;
    flex: 0 0 auto;
    min-height: var(--chip);                  /* room for the gear alongside */
    height: var(--chip);
    padding-right: calc(var(--chip) + 18px);  /* clear of the gear */
    background: url(../images/wordmark.png) center center / contain no-repeat;
    background-origin: content-box;
    font-size: 0; color: transparent;         /* hidden visually, not to AT */
  }

  .tiles{
    position: static;
    flex: 1 1 auto;
    width: auto; height: auto;
    grid-template-columns: repeat(2, 1fr);
    grid-template-rows: repeat(4, 1fr);
    column-gap: 14px;
    row-gap: 14px;
    padding: 12px;
    background: rgba(0,0,0,.55);
    border-radius: 14px;
  }

  /* The painted slots are gone, so each tile carries its own frame. */
  .tile{
    border-radius: 6px;
    padding: 9%;
    opacity: 1;
    box-shadow: 0 0 0 2px rgba(255,255,255,.85), 0 4px 14px rgba(0,0,0,.5);
  }
}

@media (prefers-reduced-motion: reduce){
  *, *::before, *::after{
    transition-duration: .01ms !important;
    animation-duration: .01ms !important;
  }
}
