/* Cosmetics shop + Analytics views */

/* === Cosmetics Shop === */
/* The block, as composed onto «Прогресс» and onto its own /shop route. */
.view-shop { max-width: 720px; margin: 0 auto; width: 100%; }
.shop-block,
.shop-grid { width: 100%; }
.shop-block { display: flex; flex-direction: column; gap: 14px; }
.shop-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
  gap: 10px;
}
.shop-item {
  padding: 14px;
  border-radius: var(--r-md);
  background: var(--panel-strong);
  border: 1px solid var(--glass-brd);
  text-align: center;
  transition: transform var(--dur-fast) var(--spring), border-color var(--dur-fast);
  cursor: pointer;
}
@media (hover: hover) {
  .shop-item:hover { transform: translateY(-3px); border-color: var(--stroke-strong); }
}
.shop-item:active { border-color: var(--stroke-strong); }
.shop-item.owned { border-color: var(--ok); }
.shop-item.equipped { border-color: var(--gold); box-shadow: var(--shadow-glow-gold); }
.shop-icon { font-size: 36px; margin-bottom: 8px; }
/* A bespoke preview plate replaces the emoji glyph for the goods that have an
   honest plate wired. Centred in the same slot the glyph holds. */
.shop-icon-img { width: 64px; height: 64px; object-fit: cover; border-radius: 12px; display: block; margin: 0 auto; }
.shop-name { font-size: 13px; font-weight: 700; margin-bottom: 4px; }
.shop-type { font-size: 11px; color: var(--text-faint); margin-bottom: 6px; }
.shop-price {
  display: inline-flex;
  align-items: baseline;
  gap: 4px;
  font-size: 14px;
  font-weight: 800;
  color: var(--gold);
}
.shop-price.owned { color: var(--ok); }
.shop-foot { display: flex; flex-wrap: wrap; gap: 8px; }
/* The block is a flex column with a gap: an element with nothing in it still
   costs a gap. The GRID is only empty in the frames before the first answer
   arrives — and that is now the only case, because it used to swallow both a
   failed load and an empty catalogue, so a 500 and a shop with nothing in it
   both rendered as a screen with no goods section at all and no word about
   why. Both fill the grid now (renderItems in views/shop.js); this rule
   covers the opening frame and nothing else. */
.shop-grid:empty { display: none; }

/* === The one currency, and it is not ours ===
   Telegram Stars are bought and their wallet is Telegram's, so the card
   carries no number on purpose — a balance we do not hold would be the first
   thing to disagree with reality. Crowns left this screen with the council's
   ruling («stop drawing ♛»); the card is capped at the width it had when it
   shared the row, because a currency card the width of the shelf reads as a
   banner, not a fact. */
.shop-cur {
  display: grid;
  grid-template-columns: minmax(0, 355px);
  gap: 10px;
}
.cur-card {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
  padding: 12px 13px;
  border-radius: var(--r-md);
  border: 1px solid var(--stroke);
  background: var(--panel-soft);
}
.cur-top { display: flex; align-items: center; gap: 7px; min-height: 25px; }
.cur-glyph { font-size: 17px; line-height: 1; }
.cur-name { font-family: var(--font-display); font-size: 12px; font-weight: 800; }
.cur-sub { font-size: 11px; line-height: 1.4; color: var(--text-soft); text-wrap: pretty; }
.cur-stars { border-color: rgba(var(--t-violet), 0.32); background: rgba(var(--t-violet), 0.07); }
.cur-stars .cur-glyph,
.cur-stars .cur-name { color: var(--violet-300); }
/* Inside a price the glyph is the currency mark, not a decoration. */
.shop-price .cur-glyph { font-size: 13px; }

/* === What money never touches ===
   Not a legal footnote — the argument for the whole screen. */
.shop-never {
  padding: 13px 14px;
  border-radius: var(--r-md);
  border: 1px dashed rgba(var(--t-violet), 0.3);
  background: rgba(var(--t-violet), 0.05);
}
.shop-never-title {
  font-family: var(--font-display);
  font-size: var(--fs-section);
  font-weight: var(--fw-section);
  letter-spacing: var(--ls-section);
  text-transform: uppercase;
  color: rgba(var(--t-gold), 0.72);
  margin-bottom: 9px;
}
.shop-never-list { display: flex; flex-wrap: wrap; gap: 6px; }
.shop-never-chip {
  padding: 5px 10px;
  border-radius: var(--r-pill);
  border: 1px solid rgba(var(--t-mute), 0.22);
  background: rgba(var(--t-mute), 0.06);
  font-size: 11.5px;
  font-weight: 700;
  color: var(--text-dim);
}

/* @container scene, not @media (shell.css «WINDOW CLASSES»): the shelf is
   inside the scene, and the scene is never the window. Upright the two agree
   at 520 — below 800px the shell is one column and scene width == window
   width, above 800 the narrowest scene is 527 — and 390 / 905 / 1280 measure
   byte-identical before and after.
   THE PHONE HELD SIDEWAYS IS WHERE THIS WAS WRONG, by 408px. There the shell
   spends 47px of window on each ear and 61–77 more on the rail: measured
   844x390 -> a 436px scene, 932x430 -> 460. The shelf was laying out
   `minmax(150px)` columns in that box because 844 is not less than 520 —
   measured `.shop-grid` at 844x390: two 197px columns in a 404px grid. After:
   three 128px columns, which is the reading this block was written for, with
   no new overflow and nothing dropping under the touch floor. */
@container scene (max-width: 520px) {
  .shop-grid { grid-template-columns: repeat(auto-fill, minmax(128px, 1fr)); }
}

/* ── Huge scene — the fifth window class (shell.css «WINDOW CLASSES») ─────
   These screens are FRAME_HOME (ui/shell.js): the context column's track is
   0, so the scene is the window minus the rail and crosses 1600px at a
   1678px window. At 1728×1080 the scene is 1650×1022 and the shelf — drawn
   at 720px for a column — left the goods as four narrow columns that
   scrolled past the bottom of a screen still showing air (measured with a
   full catalogue: 128% fill, the scene scrolling 286px). The shelf takes
   the container's width now, and the previews grow with it: the emoji
   glyphs 36 → 52px, and the bespoke plate — an 800px drawing shown at
   64px, which is why it read as a smudge — finally shows at 120px. Six
   columns at 1728, three rows of goods, and the frame does not scroll. */
@container scene (min-width: 1600px) {
  .view-shop { max-width: 1180px; }
  /* The block (not the view) is the column: renderShop mounts the title and
     then the shop-block that carries the four sections. */
  .shop-block {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    gap: 12px 16px;
  }
  .shop-block > .shop-cur,
  .shop-block > .shop-grid { grid-column: 1 / -1; }
  /* The argument and the door share the bottom row: the width is there, and
     stacked they would spend ~60px of height the goods want. */
  .shop-block > .shop-never { align-self: center; }
  .shop-block > .shop-foot { grid-column: 2; align-self: center; }
  .shop-grid { grid-template-columns: repeat(auto-fill, minmax(178px, 1fr)); gap: 10px; }
  .shop-item { padding: 14px; }
  .shop-icon { font-size: 52px; margin-bottom: 10px; }
  .shop-icon-img { width: 120px; height: 120px; border-radius: 16px; }
  .shop-name { font-size: 14px; }
  .shop-type { font-size: 12px; }
  .shop-price { font-size: 15px; }
}

/* Very large displays (2560×1440 → a 2482px scene; 1920 stays on the 1600
   tier above). The container cap (tokens.css, 1400px) is VIS1's design stop
   and is not mine to move, so the extra canvas is spent inside it: the plate
   art and the glyphs grow again, because a 120px plate on a 1440p shelf is
   still smaller than the drawing warrants. */
@container scene (min-width: 2200px) {
  .shop-item { padding: 16px; }
  .shop-icon { font-size: 60px; }
  .shop-icon-img { width: 150px; height: 150px; }
}

/* ==========================================================================
   «АНАЛИТИКА» — views/analytics.js
   The screen's BASE rules live in profile.css under this same `anl-` prefix
   (this file's header already lists the analytics view as a tenant, and
   index.html is frozen this round — profile.css § anl- documents the freeze
   and the future cut into its own stylesheet). Only the huge-scene tier
   lives here, fenced. At 1600px+ scenes the spark tape — the screen's own
   chart, the reason the screen exists — takes the height the window has
   instead of the phone's 46px: 58 readings at ~18px wide read as a chart,
   not a barcode. Measured at 1728×1080 before: 62% fill.
   ========================================================================== */
@container scene (min-width: 1600px) {
  .anl-view { gap: 16px; }
  .anl-view .panel-body { gap: 14px; padding: 16px 18px 18px; }
  .anl-view .spark-tape { height: 280px; }
  .anl-view .spark-day { border-radius: 4px 4px 0 0; }
  .anl-best-val { font-size: 40px; }
}

/* 2560×1440 (scene 2482): the chart is the screen, so on a 1440p display it
   takes the height the window has — 58 readings at ~20px wide read as a
   proper series, not the 18px bars of the 1600 tier. */
@container scene (min-width: 2200px) {
  .anl-view .spark-tape { height: 440px; }
  .anl-best-val { font-size: 48px; }
}
