/* The Grid (home). One full-screen black room. Every holder is a dressed bulb on its own cord; bulbs shrink as the crowd
   grows so thousands fit, and the room zooms (wheel, pinch, double tap) and pans (drag). Quiet text on the edges only:
   header (brand, nav, demo pill, + / - / Auto, search) on top, count, Preview sizes, camera buttons and footer below.
   The chrome wears the game's pixel kit (site.css): + / - / Auto, Fit and the camera buttons are .px-btn buttons, the
   Preview sizes one dark strip, the bulb card a wood .px-panel, the activity note a dark chip; the count is pixel. */
html,body{height:100%}
body{overflow:hidden;font-size:var(--fs-help);line-height:var(--lh-ui)}
#room{position:fixed;inset:0;width:100%;height:100%;display:block;touch-action:none;-webkit-user-select:none;user-select:none;-webkit-touch-callout:none}
#room:focus-visible{outline:2px solid var(--warm);outline-offset:-4px;border-radius:0}

/* chrome floats over the canvas; only links, buttons, the search field and the readable text catch the pointer, so bulbs
   underneath stay hoverable. (The canvas takes every touch for its own pinch zoom; over the text a pinch zooms the
   page, so small print can still be enlarged.) Once the room is crowded (body.dense, set by grid.js), a soft black
   scrim keeps the header readable. */
.overlay,.dock{position:fixed;z-index:2;left:0;right:0}
.overlay *,.dock *,.overlay,.dock{pointer-events:none}
.overlay a,.overlay button,.overlay input,.overlay .search-box,.overlay .search-msg,.overlay .results,.overlay .results *,.overlay .pill,
.dock a,.dock button,.dock .count,.dock .demo-line,.dock .note.show{pointer-events:auto}
.overlay .search-box{cursor:text}
/* the search pick list draws over the dock, its buttons and the card while it is open */
.overlay.picking{z-index:4}
/* while a phone keyboard is up the room keeps its full height under it; the dock steps aside so it doesn't land on the bulbs */
.kb .dock{visibility:hidden}
.overlay{top:0;padding:calc(14px + env(safe-area-inset-top,0px)) max(16px,env(safe-area-inset-right,0px)) 0 max(22px,env(safe-area-inset-left,0px));transition:background-color .6s}
.overlay::after{content:"";position:absolute;left:0;right:0;top:100%;height:16px;background:linear-gradient(to bottom,rgba(0,0,0,.94),rgba(0,0,0,0));opacity:0;transition:opacity .6s}
.dense .overlay,.zoomed .overlay{background-color:rgba(0,0,0,.94)}
.dense .overlay::after,.zoomed .overlay::after{opacity:1}
.dock{bottom:0;padding:0 max(16px,env(safe-area-inset-right,0px)) calc(8px + env(safe-area-inset-bottom,0px)) max(22px,env(safe-area-inset-left,0px))}
/* zoomed in, bulbs reach under the dock: a scrim fades in behind the count, sizes and footer (grid.js also leaves out
   the names that would land under the header, the dock, the camera buttons, the note, the card or the pick list) */
.dock::before{content:"";position:absolute;z-index:-1;left:0;right:0;bottom:0;top:-24px;background:linear-gradient(to bottom,rgba(0,0,0,0),rgba(0,0,0,.94) 24px);opacity:0;transition:opacity .6s}
.zoomed .dock::before{opacity:1}

/* + / - / Auto: dark-faced pixel buttons (.px-btn .px-ghost); Auto pressed is the pushed-in frame with warm text */
.ctrl{display:flex;gap:8px}
.ctrl button{display:grid;place-items:center;width:32px;height:32px;padding:0;font:400 20px/1 var(--font)}
.ctrl #auto{width:auto;padding:0 8px;font-size:var(--fs-btn);font-weight:500}

.dock-row{display:flex;flex-wrap:wrap;align-items:flex-end;justify-content:space-between;gap:10px 12px}
.count{margin:0}
.count b{display:block;font:400 clamp(36px,6vw,54px)/1 var(--font-pixel);letter-spacing:.02em;font-variant-numeric:tabular-nums;text-shadow:0 0 18px rgba(var(--glow),.35)}
.count span{display:block;margin-top:6px;font-size:var(--fs-label);font-weight:600;color:var(--faint)}
/* Preview sizes: one dark strip; the size on show is the warm face */
.scale{display:flex;align-items:center;gap:2px;padding:0 2px;border:6px solid transparent;border-image:var(--frame-dark) 2 / 6px;background:var(--plate) padding-box;image-rendering:pixelated}
.scale .name{margin:0 6px 0 4px;font-size:var(--fs-label);font-weight:600;color:var(--faint)}
.scale button{height:26px;min-width:28px;padding:0 7px;border:0;border-radius:0;background:transparent;color:var(--faint);font:500 var(--fs-btn)/1 var(--font);font-variant-numeric:tabular-nums;cursor:pointer}
.scale button:hover{color:var(--ink)}
.scale button[aria-pressed="true"]{background:var(--warm);color:var(--on-warm);font-weight:600}

.dock-foot{margin-top:12px;padding-block:9px 0;border-top-color:rgba(243,234,217,.07);line-height:1.45;gap:6px 20px}
.dock-foot .cta{padding:1px 10px}

/* activity note: a dark chip over the bulbs; the bulb card: a wood panel (.px-panel) */
.note{position:absolute;left:50%;bottom:calc(100% + 8px);transform:translateX(-50%);width:max-content;max-width:calc(100vw - 32px);margin:0;padding:1px 10px;border:6px solid transparent;border-image:var(--frame-dark) 2 / 6px;background:var(--plate) padding-box;image-rendering:pixelated;font-size:var(--fs-help);line-height:20px;color:var(--soft);text-align:center;text-wrap:balance;opacity:0;transition:opacity .6s}
.note.show{opacity:1}
.tip{position:fixed;z-index:3;margin:0;padding:2px 6px;pointer-events:none;transform:translateX(-50%);text-align:center;font-size:var(--fs-help);line-height:var(--lh-ui);color:var(--ink);white-space:nowrap}
.tip b{display:block;font-weight:600}
.tip span{display:block;font-size:var(--fs-label);color:var(--soft);font-variant-numeric:tabular-nums}
/* your own bulb's card links to your profile; only then does the card take the pointer */
.tip.linked{pointer-events:auto}
.tip a{display:block;margin:6px -6px -2px;padding:8px 6px 6px;border-top:1px solid var(--line);font-size:var(--fs-btn);font-weight:600;color:var(--warm);text-decoration:none}
.tip a:hover{color:var(--ink)}
.you{display:inline-block;margin-left:4px;padding:1px 6px;background:var(--warm);color:var(--on-warm);font-style:normal;font-size:var(--fs-tag);font-weight:600;line-height:1.4;letter-spacing:var(--track-caps);text-transform:uppercase;vertical-align:1px}

/* camera buttons (.px-btn): above the Preview row on the right. "Dress your bulb" until the wardrobe has saved one,
   then "Find my bulb"; Fit (.px-ghost) appears once zoomed in. */
.cam{position:absolute;right:max(16px,env(safe-area-inset-right,0px));bottom:calc(100% + 8px);display:flex;align-items:center;gap:6px}
.cam-btn{height:32px;padding:0 10px}
/* narrow screens: the activity note sits above the camera buttons */
@media (max-width:760px){.note{bottom:calc(100% + 52px)}}

@media (max-width:600px){
  .overlay{padding-left:max(16px,env(safe-area-inset-left,0px))}
  .dock{padding-left:max(16px,env(safe-area-inset-left,0px))}
  .ctrl button{width:38px;height:38px}
  .scale button{height:30px;min-width:32px}
  .cam-btn{height:36px}
}
@media (max-width:560px){.scale .name{display:none}.scale button{padding:0 6px}}
/* phones (430px and below, every common iPhone and Android width): the full pill plus + / - / Auto needs about 420px, so
   the pill drops "$BULB " and the row keeps Auto inside the 16px gutter, lined up with the search button above it */
@media (max-width:430px){.pill .long{display:none}}
/* small phones (down to 320px): slightly tighter controls keep the header and the Preview row on one line each, so the
   bulbs keep their room. If a font still runs wide, the rows wrap instead of running off the edge. */
@media (max-width:380px){
  .head-tail{flex-wrap:wrap;row-gap:8px;gap:8px}
  .head-tail .pill{gap:6px;padding:1px 4px}
  .ctrl{margin-left:auto;gap:6px}
  .ctrl button{width:34px;height:34px}
  .ctrl #auto{padding:0 5px}
  .dock-row{column-gap:10px}
  .scale{gap:0}
  .scale button{min-width:30px;height:28px;padding:0 4px}
}
/* 320-346px (a foldable's cover screen is 344px): the pill's decorative dot steps aside, and at 340px and below the pill
   also steps down to 12px, so the pill and + / - / Auto still share one row. The count steps down to 27px there too, so
   a 5-digit count ("10,000") still fits beside the Preview sizes and the dock row doesn't wrap into the bulbs. */
@media (max-width:346px){.head-tail .pill .dot{display:none}}
@media (max-width:340px){
  .head-tail .pill{padding:1px 2px;font-size:var(--fs-tag)}
  .ctrl{gap:5px}
  .ctrl #auto{padding:0 4px}
  .dock-row{column-gap:8px}
  .count b{font-size:27px}
}
/* phones on their side (short and wide): one compact dock row (count, camera buttons, sizes) and only the demo line
   below it, so the bulbs keep a usable room between the header and the dock */
@media (orientation:landscape) and (max-height:500px){
  .dock{display:flex;flex-wrap:wrap;align-items:flex-end;column-gap:10px}
  .dock-row{display:contents}
  .count{order:0;margin-right:auto}
  .count b{font-size:27px}
  .count span{margin-top:4px}
  .cam{position:static;order:1}
  .cam-btn{height:32px;padding:0 8px}
  .scale{order:2}
  .scale .name{display:none}
  .scale button{height:26px;min-width:30px;padding:0 5px}
  .dock-foot{order:3;flex-basis:100%;margin-top:6px;padding-top:5px}
  .dock-foot .demo-line{max-width:none}   /* one line across the whole row where it fits, so the bulbs keep their room */
  .dock-foot .foot-tail{display:none}
  .note{bottom:calc(100% + 8px)}
}
/* the smallest phones on their side (568x320): the demo line keeps to one line and the header's touch targets step down to
   34px, so the bulbs keep about 140px of room. The line opens with "This is a preview."; the pill and the "Demo holders"
   label say demo too, and screen readers still get the whole line. */
@media (orientation:landscape) and (max-height:340px){
  .overlay{padding-top:calc(10px + env(safe-area-inset-top,0px))}
  .search{top:calc(10px + env(safe-area-inset-top,0px))}
  .nav a{padding-block:8px}
  .ctrl button,.search-open{width:34px;height:34px}
  .dock-foot{min-width:0}
  .dock-foot .demo-line{min-width:0;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}
}
@media (prefers-reduced-motion:reduce){.note{transition:none}}

/* the live Grid (grid.js, "live data"). While the first live load is on its way (up to 8 s) the demo's pill, controls,
   count and camera buttons wait unseen, keeping their space so nothing moves when they show; live, the pill's dot is
   green (amber while it reconnects); an empty room gets one quiet line in the middle */
.wait .head-tail .pill,.wait .ctrl,.wait .count,.wait .scale,.wait .cam{visibility:hidden}
.pill.live.stale .dot{background:var(--warm);box-shadow:0 0 8px rgba(var(--glow),.9)}
@media (max-width:346px){.head-tail .pill.live .dot{display:block}}   /* live, the pill has the row to itself */
.empty{position:fixed;z-index:1;left:50%;top:46%;transform:translate(-50%,-50%);width:max-content;max-width:calc(100vw - 32px);margin:0;font-size:var(--fs-read);line-height:var(--lh-body);color:var(--faint);text-align:center;text-wrap:balance;pointer-events:none}
