/* APPS / PROCESSES / WEBSITES — scalable policy workspace.
 *
 * Wide screens get stable scan-down columns.  At phone widths the very same
 * cells become labelled, full-width cards; no table is horizontally scrolled
 * or squeezed below the 320px iPhone SE target.  State colours always retain
 * words and icons, so colour is never the only signal.
 */

.pw-icon {
  width: 17px;
  height: 17px;
  flex: 0 0 17px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.9;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.pw-icon-label {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  min-width: 0;
}

.pw-toolbar {
  display: grid;
  grid-template-columns: minmax(220px, 1fr) minmax(150px, .45fr) minmax(150px, .45fr);
  gap: 10px;
  align-items: end;
  margin: 16px 0 12px;
}

.pw-tool {
  display: grid;
  gap: 5px;
  min-width: 0;
}

.pw-tool-label {
  color: var(--haze);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: .07em;
  text-transform: uppercase;
}

.pw-input-shell {
  position: relative;
  display: flex;
  align-items: center;
  min-width: 0;
}

.pw-input-shell > .pw-icon {
  position: absolute;
  left: 12px;
  z-index: 1;
  color: var(--haze);
  pointer-events: none;
}

.pw-input-shell > .inp {
  width: 100%;
  min-width: 0;
  padding-left: 38px;
}

.pw-table-head {
  display: grid;
  align-items: center;
  gap: 14px;
  padding: 0 14px 8px;
  color: var(--haze);
  font-size: 11px;
  font-weight: 750;
  letter-spacing: .07em;
  text-transform: uppercase;
}

.pw-row {
  display: grid;
  align-items: center;
  gap: 14px;
  min-width: 0;
  margin: 0;
  padding: 14px;
  border: 1px solid var(--line);
  border-radius: 14px;
  background: color-mix(in srgb, var(--dusk2) 72%, transparent);
}

.pw-row + .pw-row { margin-top: 8px; }

/* 44px AND NOT 42px IN THE LAST TRACK, AND THE 2px COMES OUT OF THE LIMIT
 * COLUMN SO THE TOTAL DOES NOT MOVE. `.pw-more-button` is declared `width:
 * 44px` — squarely, because it is an icon button with no text and its WIDTH is
 * its smaller dimension against the touch target. A 42px track around a 44px
 * button put 2px of that button outside its own cell at every table width,
 * measured in en, es and fr and in both themes. Taking the 2px from the
 * limit column keeps the sum of the minimums at 719px, which is the number the
 * 1199px breakpoint below is derived from. */
.pw-process-head,
.pw-process-row {
  grid-template-columns:
    minmax(130px, 1.25fr)
    minmax(100px, .8fr)
    minmax(135px, 1.15fr)
    minmax(220px, 1.5fr)
    minmax(90px, .7fr)
    44px;
}

.pw-app-head,
#invList .pw-app-row {
  grid-template-columns:
    minmax(120px, 1fr)
    minmax(125px, 1.1fr)
    minmax(100px, .8fr)
    minmax(220px, 1.45fr)
    minmax(94px, .72fr)
    42px;
}

/* SIX CHILDREN, AND ONLY FIVE TRACKS WERE DECLARED.
 *
 * `siteWorkspaceRow` appends the host avatar FIRST and then the five cells
 * this list names, so every website row had an implicit sixth column the grid
 * never sized. MEASURED at 1440 and at 3840, en/light, before this change: the
 * workspace overflowed its own box by 35-50px on every tab — the avatar's
 * 34px plus one 14px gap, pushed off the end — and the column labels above the
 * rows were one cell out of line with the cells they name. The avatar is now
 * the first declared track and `.pw-site-head` gets a matching empty leading
 * cell (see renderSitesWorkspace), so the two agree by construction.
 *
 * The content minimums come down with it. 170+190+150+150+42 plus four gaps
 * and the row's own padding demanded 786px of content width, which is more
 * than a 900px laptop has beside the 250px rail. */
.pw-site-head,
#sitesList .pw-site-row {
  grid-template-columns:
    34px
    minmax(140px, 1.1fr)
    minmax(160px, 1.25fr)
    minmax(120px, .9fr)
    minmax(140px, .9fr)
    44px;
}

#sites .pw-sites-panels { display: block; }
#sites .pw-site-panel { min-width: 0; }
#sites .pw-site-panel[hidden] { display: none; }
#sites .pw-site-panel > .rulehead { margin-bottom: 10px; }
#sitesList .pw-site-row > .favicon { align-self: start; margin-top: 2px; }
#sitesList .pw-site-row > .pw-state-cell {
  display: flex;
  flex-wrap: wrap;
  gap: 7px;
  align-items: center;
}

#invList .pw-app-head { margin: 10px 0 0; }
#invList .invBacklogRows > .pw-app-head { margin-top: 0; }

/* The prior wide-screen card grid put two unrelated app rows beside each
 * other.  Stable columns need the full card width so values scan vertically. */
@media (min-width: 1200px) {
  #invList .invDecisionGroup { display: block; }
  #invList .invDecisionGroup > .pw-row,
  #invList .invDecisionGroup > .invMoreGroup { margin-top: 8px; }
  #invList .invMoreRows,
  #invList .invBacklogRows { grid-template-columns: minmax(0, 1fr); }
}

.pw-cell { min-width: 0; }

/* ---------------------------------------------------------------------------
   LONG TEXT WRAPS OR ELLIPSIZES INSIDE ITS OWN CELL, NEVER OVER A NEIGHBOUR.
   ---------------------------------------------------------------------------
   `min-width: 0` above only lets a TRACK shrink. It says nothing about what
   the ink inside the track does when the string is longer than the track is
   wide, and three strings on these rows routinely are:

     * A CATEGORY. `.pill` is `white-space: nowrap` everywhere on this
       dashboard, which is right for "Safe" and "3 waiting" and wrong for a
       classifier category. MEASURED at 1440x900, en: "Games & entertainment"
       is 146px of unbreakable text and it was drawn 46px outside its own cell
       and 32px into the description sentence beside it. Scoped to
       `.pw-rating-stack` so the nowrap every short pill relies on is
       untouched.

     * AN ACCESS LABEL. `.pw-state-option` is a 44px-tall button whose width is
       a share of one grid track, and its `.pw-icon-label` is an inline-flex
       that does not shrink: at 1440 the "Block" button was 22px wide and its
       label was drawn from 1306 to 1336, i.e. 14px past the button and across
       "View limits" in the next cell. `Voir les limites` and `Temporaire` make
       fr worse than en, which is why the ellipsis is here and not in a
       language-specific override.

     * A DAILY-LIMIT LABEL, for the same reason and in the same shape.

   The clamp is on the LABEL, not on the button: `.sw::before` (app.css) is the
   invisible hit-area expander that keeps these controls at their touch size,
   and `overflow: hidden` on the button itself would clip it. What the label
   then DOES with a string too long for it — wrap, and only clip as a last
   resort — is the rule below, with the measurement that chose it.
   --------------------------------------------------------------------------- */
.pw-rating-stack .pill {
  max-width: 100%;
  white-space: normal;
  overflow-wrap: anywhere;
}

.pw-state-option > .pw-icon-label,
.pw-limit-button > .pw-icon-label {
  max-width: 100%;
  overflow: hidden;
}

/* WRAP FIRST, ELLIPSIS ONLY AS THE LAST RESORT. An earlier version of this
 * rule was `white-space: nowrap` + `text-overflow: ellipsis`, which did stop
 * the overlap and cost too much to keep: MEASURED at 1440x900 in fr, the
 * access control's own labels lost 25px of "Autoriser" and 16px of "Bloquer",
 * i.e. about half of each word, on the one control that decides whether a
 * child can open an app. Wrapping keeps the whole word — this file's opening
 * contract is that these controls "always retain words and icons, so colour is
 * never the only signal", and half a word is not the word. `anywhere` because
 * these labels are single words with nothing to break at, `overflow: hidden`
 * so a label that STILL does not fit is clipped inside its own button instead
 * of painted across the cell beside it, and the ellipsis stays for the
 * one-line case a future longer string might hit. */
.pw-icon-label-text {
  min-width: 0;
  overflow: hidden;
  overflow-wrap: anywhere;
  text-overflow: ellipsis;
}

.pw-main-name {
  display: block;
  color: var(--cloud);
  font-size: 14px;
  font-weight: 720;
  overflow-wrap: anywhere;
}

.pw-secondary,
.pw-description {
  display: block;
  color: var(--haze);
  font-size: 12px;
  font-weight: 400;
  line-height: 1.4;
  overflow-wrap: anywhere;
}

.pw-row-detail { display: none; }

/* app.css has an older, deliberately high-specificity rule that turns every
 * `.asub` below an inventory name into inline prose.  These are the same facts
 * now represented by stable columns, so keep their row-only copies out of both
 * layout and the accessibility tree.  Without the matching specificity they
 * reappear at 320px and physically paint through the controls below them. */
#invList .pw-app-row .pw-main-cell > .pw-row-detail { display: none; }

#invList .pw-app-row .atime {
  width: auto;
  min-width: 0;
  max-width: none;
  margin-top: 4px;
  color: var(--haze);
  text-align: left;
}

.pw-description { margin-top: 3px; }

/* A FIXED 44px HEIGHT CLIPS A WRAPPED LABEL, so on this row the 44px is a
 * FLOOR and not a ceiling. `.pw-state-option` declares `height: 44px` as well
 * as `min-height: 44px`; with the wrap above, "Bloquear" and "Autoriser" take
 * two lines in the narrowest table columns and MEASURED 22px of that second
 * line was cut off at 1199-1280 in es and fr. `height: auto` keeps the floor
 * (the touch target is `min-height`, untouched), and the three segments stay
 * the same height as each other because `.pw-state-control` is a grid and its
 * items stretch. Scoped to the process row: Apps and Websites size these same
 * segments from wider tracks and neither was measured clipping. */
.pw-process-row .pw-state-option,
.pw-process-row .pw-state-control .sw { height: auto; }

/* `max-width` IS WHAT MAKES `max-content` SAFE. Without it the Close now
 * button is exactly as wide as its own label wants to be, whatever the name
 * column happens to be — and "Fermer maintenant" is 13px wider than that
 * column at 1200px, so the button hung out of the cell it lives in. Capped, it
 * wraps its label instead, which is the behaviour every other control on the
 * row already has. */
.pw-process-row .proc-close {
  display: block;
  width: max-content;
  max-width: 100%;
  margin-top: 8px;
}

.pw-meta-stack,
.pw-rating-stack {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px;
}

.pw-meta-stack .pill,
.pw-rating-stack .pill { margin: 0; }

.pw-state-control {
  display: grid;
  grid-template-columns: minmax(0, .85fr) minmax(0, 1.3fr) minmax(0, .85fr);
  gap: 3px;
  min-width: 0;
  padding: 3px;
  border: 1px solid var(--line);
  border-radius: 12px;
  background: var(--dusk2);
}

/* 44px, NOT 36. Every control in this file is one a parent taps on a phone,
 * and the acceptance size for this product is a 320px screen. At 36px the
 * three-way Allow / Temporary / Block choice was under the 44px touch target
 * on every one of the five validated widths — and it is the control that
 * decides whether a child can open an app, so a mis-tap here is a wrong
 * policy, not a cosmetic annoyance. The row is a flex/grid column on a phone
 * and a wide grid on a desktop; neither reflows from 8 more pixels. Raised
 * here rather than inside a phone-only media query on purpose: a pointer:fine
 * exemption would leave the two touch-first sizes (768 tablet portrait and a
 * 440 phone in landscape) reading as "desktop" on hardware that is neither. */
.pw-state-option,
.pw-state-control .sw {
  position: relative;
  width: auto;
  min-width: 0;
  height: 44px;
  min-height: 44px;
  padding: 0 8px;
  border: 1px solid transparent;
  border-radius: 8px;
  background: transparent;
  color: var(--haze);
  font: inherit;
  font-size: 11px;
  font-weight: 700;
  cursor: pointer;
}

/* `.sw` remains the legacy test/action hook on Apps and Processes, but its
 * old one-knob painting is not a second state language inside this control. */
.pw-state-control .sw::after { display: none; }
.pw-state-control .sw::before { inset: -4px; }

.pw-state-option:hover:not(:disabled),
.pw-state-option:focus-visible {
  border-color: var(--track);
  color: var(--cloud);
}

.pw-state-option.is-selected.pw-state-allowed {
  border-color: var(--mint);
  background: color-mix(in srgb, var(--mint) 13%, transparent);
  color: var(--done-text);
}

.pw-state-option.is-selected.pw-state-blocked {
  border-color: var(--coral);
  background: color-mix(in srgb, var(--coral) 13%, transparent);
  color: var(--coral);
}

.pw-state-option.is-selected.pw-state-temporary {
  border-color: var(--amber);
  background: color-mix(in srgb, var(--amber) 13%, transparent);
  color: var(--waiting-text);
}

.pw-state-option.is-unavailable {
  border-style: dashed;
  opacity: .76;
}

.pw-state-option:disabled { cursor: wait; opacity: .58; }

:root[data-theme="light"] .pw-state-option.is-selected.pw-state-allowed,
:root:not([data-theme]) .pw-state-option.is-selected.pw-state-allowed { color: #0A6242; }
:root[data-theme="light"] .pw-state-option.is-selected.pw-state-blocked,
:root:not([data-theme]) .pw-state-option.is-selected.pw-state-blocked { color: #B23127; }
:root[data-theme="light"] .pw-state-option.is-selected.pw-state-temporary,
:root:not([data-theme]) .pw-state-option.is-selected.pw-state-temporary { color: #7A4F00; }

.pw-limit-button,
.pw-more-button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 7px;
  width: 100%;
  min-height: 44px;
  padding: 7px 9px;
  border: 1px solid var(--line);
  border-radius: 10px;
  background: transparent;
  color: var(--cloud);
  font: inherit;
  font-size: 12px;
  cursor: pointer;
}

/* Square, and both sides count. This one is an icon button with no text, so
 * its WIDTH was the smaller of its two dimensions at 40px — the reason a
 * height-only sweep would have called it compliant. */
.pw-more-button {
  width: 44px;
  padding: 0;
  color: var(--haze);
}

.pw-limit-button:hover,
.pw-limit-button:focus-visible,
.pw-more-button:hover,
.pw-more-button:focus-visible {
  border-color: var(--glow);
  color: var(--glow);
}

.pw-pager {
  display: grid;
  grid-template-columns: minmax(88px, auto) 1fr minmax(88px, auto);
  gap: 10px;
  align-items: center;
  margin-top: 14px;
}

.pw-page-button { min-height: 44px; }

/* THE CONTROLS THESE ROWS BORROW FROM app.css, BROUGHT UP TO THE SAME TARGET.
 *
 * `.iconbtn` (the Websites row's Remove) and `.ghost.small` (Review, Close
 * now, Open limit settings) are shared classes defined in app.css at roughly
 * 34px tall — below the 44px touch target on every width this workspace is
 * validated at. They are scoped HERE, to the workspace rows, rather than
 * raised in app.css: that file is shared with a dozen screens other lanes are
 * editing, and a global size change is not this lane's to make. Remove in
 * particular is DESTRUCTIVE and sits beside a decision pill, which is the
 * worst place on the screen to have to aim. */
.pw-row .iconbtn,
.pw-row .ghost.small,
.pw-detail-device .ghost {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 44px;
  min-width: 44px;
}

.pw-page-status {
  color: var(--haze);
  font-size: 12px;
  text-align: center;
}

.pw-tabs {
  display: flex;
  gap: 6px;
  margin: 12px 0;
  padding: 4px;
  overflow-x: auto;
  border: 1px solid var(--line);
  border-radius: 13px;
  background: var(--dusk2);
  scrollbar-width: thin;
}

.pw-tab {
  flex: 1 0 auto;
  min-height: 44px;
  padding: 8px 12px;
  border: 1px solid transparent;
  border-radius: 9px;
  background: transparent;
  color: var(--haze);
  font: inherit;
  font-size: 12px;
  font-weight: 700;
}

.pw-tab[aria-selected="true"] {
  border-color: var(--glow);
  background: color-mix(in srgb, var(--glow) 12%, transparent);
  color: var(--glow);
}

:root[data-theme="light"] .pw-tab[aria-selected="true"],
:root:not([data-theme]) .pw-tab[aria-selected="true"] { color: #075F82; }

.pw-dialog {
  width: min(680px, calc(100vw - 28px));
  max-height: min(780px, calc(100dvh - 28px));
  margin: auto;
  padding: 0;
  overflow: hidden;
  border: 1px solid var(--line);
  border-radius: 20px;
  background: var(--dusk);
  color: var(--cloud);
  box-shadow: var(--shadow);
}

.pw-dialog::backdrop { background: rgba(3, 9, 18, .72); backdrop-filter: blur(4px); }
/* Same lighter scrim app.css already gives .stepup-dialog::backdrop and
 * .schedule-dialog::backdrop in light theme -- this dialog's own light
 * override was missing, so a light-toggled parent got the dark-theme .72
 * near-opaque scrim behind an otherwise correctly light dialog box (visually
 * read as "the whole screen went dark"). Confirmed by screenshot 2026-09-19. */
:root[data-theme="light"] .pw-dialog::backdrop,
:root:not([data-theme]) .pw-dialog::backdrop { background: rgba(10,16,32,.42); }

.pw-dialog-shell {
  display: grid;
  grid-template-rows: auto minmax(0, 1fr) auto;
  max-height: min(780px, calc(100dvh - 28px));
}

.pw-dialog-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 16px;
  padding: 18px 18px 14px;
  border-bottom: 1px solid var(--line);
}

.pw-dialog-eyebrow {
  margin-bottom: 3px;
  color: var(--glow);
  font-size: 11px;
  font-weight: 750;
  letter-spacing: .08em;
  text-transform: uppercase;
}

.pw-dialog-title { font-size: clamp(19px, 4vw, 25px); line-height: 1.2; }

.pw-dialog-close {
  display: grid;
  place-items: center;
  width: 42px;
  height: 42px;
  flex: 0 0 42px;
  border: 1px solid var(--line);
  border-radius: 12px;
  background: var(--dusk2);
  color: var(--haze);
}

.pw-dialog-close:hover,
.pw-dialog-close:focus-visible { border-color: var(--glow); color: var(--glow); }

.pw-dialog-body {
  display: grid;
  gap: 12px;
  padding: 16px 18px 22px;
  overflow: auto;
  overscroll-behavior: contain;
}

.pw-detail-section {
  padding: 13px 14px;
  border: 1px solid var(--line);
  border-radius: 13px;
  background: var(--dusk2);
}

.pw-detail-heading {
  margin-bottom: 5px;
  color: var(--cloud);
  font-size: 13px;
}

.pw-detail-copy { color: var(--haze); font-size: 13px; overflow-wrap: anywhere; }

.pw-detail-list { display: grid; gap: 8px; }

.pw-detail-device {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: 10px;
  align-items: center;
  padding: 10px 0;
  border-bottom: 1px solid var(--line);
}

.pw-detail-device:last-child { border-bottom: 0; padding-bottom: 0; }
.pw-detail-device:first-child { padding-top: 0; }

.pw-dialog-actions {
  display: flex;
  justify-content: flex-end;
  gap: 8px;
  padding: 12px 18px max(12px, env(safe-area-inset-bottom));
  border-top: 1px solid var(--line);
  background: var(--dusk);
}

/* THE TABLE NEEDS ROOM IT DOES NOT HAVE UNTIL ~1100px, AND 760 WAS NOT WHERE
 * THAT HAPPENS.
 *
 * MEASURED on the Websites workspace, all four tabs, before this change:
 *
 *   768px   the PAGE scrolled sideways by 87-192px, in every theme and every
 *           language (fr worst, because its longer decision words widen the
 *           columns that were already over budget)
 *   1440px  no page scroll, but the workspace still overflowed its own box
 *
 * The arithmetic behind it: these rows are five or six columns whose minimums
 * total ~700px, plus four 14px gaps and 28px of row padding — about 786px of
 * CONTENT. app.css keeps the phone navigation shell until 899.98px and then
 * hands the page a 250px rail, so the content column is roughly 768px at a
 * 768px tablet and roughly 600px at a 900px laptop. The table has never fitted
 * either. It first fits at about 1100px, and that is where this now switches.
 *
 * BELOW IT IS NOT A CRUSHED TABLE, it is the card stack these rules build —
 * the same one the 320px phone gets. A cramped six-column table on a 1024px
 * laptop is not more information than five readable stacked facts; it is the
 * same information, unreadable, next to a horizontal scrollbar.
 *
 * policy-workspace-ui.test.js pins this number. If it moves again, move it
 * there in the same commit and say what was measured. */
@media (max-width: 1099.98px) {
  .pw-toolbar { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }
  .pw-search-tool { grid-column: 1 / -1; }
  .pw-table-head { display: none; }

  .pw-row {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    gap: 12px;
    padding: 14px;
    align-items: start;
  }

  /* Processes carry more independent facts than the older four-column row.
   * Leaving them in the generic two-track phone grid lets auto-placement put
   * Rating, description, limit and More into narrow side-by-side cells.  Use
   * the same deliberate card stack as Apps, with More anchored to the title
   * row, so every value has a full 320px-phone content track. */
  .arow.procrow.pw-process-row {
    position: relative;
    display: flex;
    flex-direction: column;
    align-items: stretch;
    gap: 12px;
  }
  .arow.procrow.pw-process-row > .pw-cell {
    width: 100%;
    min-width: 0;
  }
  .arow.procrow.pw-process-row > .pw-main-cell { padding-right: 52px; }
  .arow.procrow.pw-process-row > .pw-more-cell {
    position: absolute;
    top: 12px;
    right: 12px;
    width: 44px;
  }
  .arow.procrow.pw-process-row > .pw-state-cell,
  .arow.procrow.pw-process-row > .pw-limit-cell { align-self: stretch; }
  /* Inventory has years of legacy `.arow` phone-grid rules in apps.css. A
   * flex column here deliberately removes those named grid areas instead of
   * trying to win six separate cascade fights. The result is one predictable
   * full-width card at the 320px acceptance size: identity, description,
   * rating, access, then limit. The More action is pinned to the identity row
   * and never consumes a narrow text column. */
  #invList .pw-app-row {
    position: relative;
    display: flex;
    flex-direction: column;
    align-items: stretch;
    gap: 12px;
    padding: 14px;
  }
  #invList .pw-app-row > .pw-cell {
    width: 100%;
    min-width: 0;
  }
  #invList .pw-app-row > .pw-main-cell { padding-right: 52px; }
  #invList .pw-app-row > .pw-more-cell {
    position: absolute;
    top: 12px;
    right: 12px;
    width: 44px;
  }
  #invList .pw-app-row > .pw-state-cell,
  #invList .pw-app-row > .pw-limit-cell { align-self: stretch; }

  #sitesList .pw-site-row {
    grid-template-columns: 34px minmax(0, 1fr) 44px;
    grid-template-areas:
      "avatar main more"
      "description description description"
      "rating rating rating"
      "state state state";
  }
  #sitesList .pw-site-row > .favicon { grid-area: avatar; }
  #sitesList .pw-site-row > .pw-main-cell { grid-area: main; }
  #sitesList .pw-site-row > .pw-description-cell { grid-area: description; }
  #sitesList .pw-site-row > .pw-rating-cell { grid-area: rating; }
  #sitesList .pw-site-row > .pw-state-cell { grid-area: state; }
  #sitesList .pw-site-row > .pw-more-cell { grid-area: more; }

  .pw-main-cell,
  .pw-state-cell { grid-column: 1 / -1; }

  .pw-cell:not(.pw-main-cell):not(.pw-state-cell)::before {
    content: attr(data-label);
    display: block;
    margin-bottom: 4px;
    color: var(--haze);
    font-size: 10px;
    font-weight: 750;
    letter-spacing: .06em;
    text-transform: uppercase;
  }

  .pw-more-cell { align-self: end; }
}

/* PROCESSES KEEPS THE CARD STACK 99px LONGER THAN THE OTHER TWO WORKSPACES,
 * AND THE NUMBER IS ARITHMETIC RATHER THAN TASTE.
 *
 * The block above switches every workspace back to a table at 1100px. That was
 * derived for the five-column Websites row, and for Processes it was never
 * TESTED, because until app.css stopped claiming `.arow.procrow.pw-process-row`
 * the six-track template above had not actually been in force at any width —
 * the legacy five-track table was (see the `:not(.pw-process-row)` comment in
 * app.css). With the real tracks applied, this row's own declared minimums are
 *
 *     130 + 100 + 135 + 220 + 90 + 44          = 719px of tracks
 *     + 5 gaps x 14px                          =  70px
 *     + the row's 14px padding x2 and 1px border x2  =  30px
 *                                              = 819px of ROW
 *
 * and MEASURED on this dashboard the process card is `viewport - 380px` wide
 * wherever the family rail is up (L315/R1215 at 1280, L315/R1375 at 1440), so
 * the table first fits at 1199px. Asked for it at 1100 the page scrolled
 * sideways by 18px and the access control had 46px to draw three words in.
 *
 * SO THE STACK, NOT A SQUEEZED TABLE — the argument the block above already
 * makes, applied to the row it is actually true of. These are the same five
 * rules that block sets, restated for the 1100-1198.98 band rather than
 * widened in place, so nothing about Apps, Websites or any width below 1100
 * moves by a pixel; the per-cell labels come with them, because a stacked card
 * whose values have lost their column headings is not readable either.
 *
 * If this number moves, move it with a measurement: the row width at the new
 * breakpoint, and the sum of the track minimums it has to hold.
 * platform/test/processes-layout.test.js measures 1024/1100/1200/1280 for
 * exactly this reason. */
@media (min-width: 1100px) and (max-width: 1198.98px) {
  .pw-process-head { display: none; }

  .arow.procrow.pw-process-row {
    position: relative;
    display: flex;
    flex-direction: column;
    align-items: stretch;
    gap: 12px;
  }
  .arow.procrow.pw-process-row > .pw-cell {
    width: 100%;
    min-width: 0;
  }
  .arow.procrow.pw-process-row > .pw-main-cell { padding-right: 52px; }
  .arow.procrow.pw-process-row > .pw-more-cell {
    position: absolute;
    top: 12px;
    right: 12px;
    width: 44px;
  }
  .arow.procrow.pw-process-row > .pw-state-cell,
  .arow.procrow.pw-process-row > .pw-limit-cell { align-self: stretch; }

  .arow.procrow.pw-process-row > .pw-cell:not(.pw-main-cell):not(.pw-state-cell)::before {
    content: attr(data-label);
    display: block;
    margin-bottom: 4px;
    color: var(--haze);
    font-size: 10px;
    font-weight: 750;
    letter-spacing: .06em;
    text-transform: uppercase;
  }
}

@media (max-width: 420px) {
  .pw-toolbar { grid-template-columns: 1fr; }
  .pw-search-tool { grid-column: auto; }
  .pw-state-option,
  .pw-state-control .sw { padding-inline: 5px; font-size: 10px; }
  .pw-icon-label { gap: 4px; }
  .pw-icon { width: 15px; height: 15px; flex-basis: 15px; }
  .pw-pager { grid-template-columns: 1fr 1fr; }
  .pw-page-status { grid-column: 1 / -1; grid-row: 1; }
  .pw-dialog {
    width: calc(100vw - 12px);
    max-height: calc(100dvh - 12px);
    border-radius: 17px;
  }
  .pw-dialog-shell { max-height: calc(100dvh - 12px); }
  .pw-dialog-head { padding: 15px 14px 12px; }
  .pw-dialog-body { padding: 13px 14px 18px; }
  .pw-detail-device { grid-template-columns: 1fr; }
  .pw-detail-device .ghost { width: 100%; }
}

@media (max-width: 340px) {
  /* Three complete words are more valuable than three crushed icon/word
   * pairs on the narrowest supported phone. Icons remain in the limit and
   * details actions; accessible names and visible state words are unchanged. */
  .pw-state-control .pw-icon { display: none; }
  .pw-state-control .pw-icon-label { gap: 0; }
}

@media (prefers-reduced-motion: reduce) {
  .pw-dialog::backdrop { backdrop-filter: none; }
}

/* =========================================================================
 * ONE APP'S SETTINGS — the name that opens it, and what the view holds.
 *
 * THE NAME IS A BUTTON NOW (app.js `inventoryRow`), because the owner asked
 * for exactly that: "make it so you can click on them and it takes you to
 * setting for thea app". These rules make it LOOK like the name it replaced
 * rather than like a control — a pill or a fill on every row of a
 * two-hundred-row list is noise, and the row already carries three real
 * buttons whose shapes mean something. The affordance is carried by the
 * underline on hover and by a real focus ring, not by a box.
 *
 * `button` in app.css sets font-weight 700 and a 13px radius on every button
 * on the page, so both are overridden here rather than inherited: 720 is
 * `.pw-main-name`'s weight, which is what this text used to be.
 * ===================================================================== */
.pw-app-open {
  display: block;
  width: 100%;
  padding: 0;
  border-radius: 4px;
  background: none;
  color: var(--cloud);
  font-size: 14px;
  font-weight: 720;
  line-height: 1.3;
  text-align: left;
  overflow-wrap: anywhere;
}

.pw-app-open:hover { color: var(--glow); text-decoration: underline; }

/* THE TOUCH TARGET IS THE ROW'S, NOT THE TEXT'S, AND THAT IS DELIBERATE. A
 * name is as tall as its own line box; a 44px min-height here would push every
 * row of a two-hundred-row list apart by a blank half-line and turn the screen
 * back into the scrolling document the workspace redesign was built to end.
 * The hit area is widened rather than heightened — the button spans the whole
 * name column (`width: 100%`, `display: block`) and the row's own 14px of
 * padding sits above and below it, which is what a thumb actually lands on.
 * The row's More control remains a full 44px target for the same view. */

.appdetail-now { color: var(--cloud); font-size: 13px; font-weight: 600; }

/* A DIFFERENCE BETWEEN CHILDREN IS A WARNING, NOT A DECORATION. Amber is this
 * page's "something here needs your attention" and mint is "this is fine";
 * painting a per-child disagreement mint would tell a parent the household
 * agrees when it does not. */
.appdetail-differs { color: var(--waiting-text); font-weight: 600; }
.appdetail-same { color: var(--haze); }

/* A REFUSED WRITE IS ATTENTION, THE SAME AMBER AS `.appdetail-differs` —
 * round-4 audit finding #10. This is the sentence #invMsg already carries on
 * the page behind this dialog's own backdrop; painting it any other colour
 * here would make it read as decoration rather than as the reason the switch
 * just snapped back. */
.appdetail-error { color: var(--waiting-text); font-weight: 600; }

.appdetail-child,
.appdetail-device {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: 10px;
  align-items: center;
  padding: 10px 0;
  border-bottom: 1px solid var(--line);
}

.appdetail-child:last-child,
.appdetail-device:last-child { border-bottom: 0; padding-bottom: 0; }

.appdetail-device { grid-template-columns: minmax(0, 1fr); align-items: start; }

.appdetail-child-name,
.appdetail-device-name { display: block; }

.appdetail-child-state { display: block; }

.appdetail-device-unknown { color: var(--haze); font-size: 13px; }

.appdetail-effects {
  display: grid;
  gap: 6px;
  margin: 6px 0 0;
  padding: 0;
  list-style: none;
}

.appdetail-effect {
  color: var(--haze);
  font-size: 12px;
  line-height: 1.45;
  overflow-wrap: anywhere;
  padding-left: 11px;
  border-left: 2px solid var(--line);
}

/* A CONTROL THAT DOES NOT BITE ON THIS DEVICE. Amber, and a heavier rule, for
 * the same reason `.appdetail-differs` is amber: this is the sentence that
 * stops a parent believing a switch is protecting a machine it cannot reach.
 * The words say it too — colour is never the only carrier here. */
.appdetail-inert { color: var(--waiting-text); border-left-color: var(--amber); }

/* The Temporary explanation is what the unavailable Temporary control scrolls
 * to, so it keeps a little room above it inside the dialog's own scroller —
 * without it the heading lands flush against the sticky head and reads as cut
 * off. */
.appdetail-temporary { scroll-margin-block: 10px; }

@media (max-width: 420px) {
  /* The child rows keep their action, stacked, for the same reason
   * `.pw-detail-device` does: a 44px button beside a 60-character child name
   * on a 390px phone crushes the name into a vertical column of letters. */
  .appdetail-child { grid-template-columns: 1fr; }
  .appdetail-child .ghost { width: 100%; }
}
