/* TFM v8 -- the shell. src/web/shared/tfm-shell.css
   NO COLOUR LITERAL APPEARS HERE. Every colour is a custom property DEFINED IN
   shared/tfm-tokens.css, which is the one colour file unit 4 requirement 1
   names. The tokens used to be written onto :root from JavaScript; they are
   plain CSS now, because a page that loses its palette when a module fails to
   link is a page whose styling depends on code executing. Measured live. */
* { box-sizing: border-box; }
body { margin: 0; font: 15px/1.55 system-ui, -apple-system, Segoe UI, sans-serif;
       background: var(--tfm-ground); color: var(--tfm-ink); }

/* Bare form controls, so a page that has not reached for .tfm-btn still sits on
   the palette. Without this a plain <button> renders in the browser's own
   colours -- light grey on a dark ground, which is how admin and dashboard
   looked. */
button, input, select, textarea {
  font: inherit; color: var(--tfm-ink); background: var(--tfm-panel);
  border: 1px solid var(--tfm-edge); border-radius: .4rem; padding: .35rem .6rem;
}
button { cursor: pointer; }
button:hover, input:focus, select:focus, textarea:focus {
  border-color: var(--tfm-accent); outline: none;
}
button[disabled] { opacity: .5; cursor: default; border-color: var(--tfm-edge); }
a { color: var(--tfm-accent); }
h1, h2, h3 { line-height: 1.2; margin: 0 0 .5rem; }

.tfm-bar { display: flex; align-items: center; gap: 1rem; padding: .55rem 1rem;
           background: var(--tfm-panel); border-bottom: 1px solid var(--tfm-edge); }
.tfm-logo { display: flex; align-items: center; gap: .5rem; font-weight: 600; }
.tfm-logo .mark { width: 1.6rem; height: 1.6rem; border-radius: .35rem;
                  background: var(--tfm-accent); color: var(--tfm-accent-ink);
                  display: grid; place-items: center; font-weight: 700; }
.tfm-bar .spacer { flex: 1; }
.tfm-bar .who { color: var(--tfm-ink-muted); font-size: .9rem; }

.tfm-btn { font: inherit; padding: .4rem .85rem; border-radius: .4rem; cursor: pointer;
           border: 1px solid var(--tfm-edge); background: transparent; color: var(--tfm-ink); }
.tfm-btn:hover { border-color: var(--tfm-accent); }
.tfm-btn.primary { background: var(--tfm-accent); color: var(--tfm-accent-ink);
                   border-color: var(--tfm-accent); font-weight: 600; }

.tfm-card { display: block; background: var(--tfm-panel); border: 1px solid var(--tfm-edge);
            border-radius: .6rem; padding: 1rem; text-decoration: none; color: inherit; }
.tfm-card:hover { border-color: var(--tfm-accent); }
.tfm-grid { display: grid; gap: 1rem; grid-template-columns: repeat(auto-fill, minmax(15rem, 1fr));
            padding: 1.5rem; max-width: 78rem; }
.tag { display: inline-block; font-size: .68rem; letter-spacing: .04em; text-transform: uppercase;
       padding: .12rem .45rem; border-radius: .25rem; border: 1px solid var(--tfm-edge);
       color: var(--tfm-ink-muted); margin: .1rem .2rem .1rem 0; }
.tag.live { color: var(--tfm-live); border-color: var(--tfm-live); }
.tag.admin { color: var(--tfm-admin-tag); border-color: var(--tfm-admin-tag); }
.muted { color: var(--tfm-ink-muted); }
.msg { border: 1px solid var(--tfm-edge); border-radius: .4rem; padding: .7rem; margin-top: .7rem;
       background: var(--tfm-panel); }
.msg[hidden] { display: none; }

/* ---- panels ---------------------------------------------------------------
   shared/tfm-panels.js makes an element draggable, closable and Escape-
   dismissable, and NOTHING USED IT -- because there was no `.tfm-panel` rule
   anywhere, so a panel had no position, no ground and no size to resize. The
   behaviour existed and could not be seen. `resize: both` is the resizing half:
   the module deliberately leaves it to CSS rather than reimplementing a corner
   grip in JavaScript. */
/* max-width and min-width both yield to the VIEWPORT. `tfm-panels.place()` clamps the
   position; these clamp the size, and both halves are needed -- a panel placed inside a
   360px screen still overflows it if its own minimum is 15rem = 240px and its maximum is
   32rem = 512px. The owner met the result on a phone: right-hand text cut off with no way
   to reach it. `min()` rather than a media query, so there is one rule rather than a
   breakpoint somebody has to keep in step with `place()`. */
/* **RESIZABLE MEANS THE OPERATOR CAN MAKE IT BIGGER, AND `max-width: 32rem` MEANT THEY
   COULD NOT** *(owner, brief 4 section 4: "a fixed box with a scrollbar; on a wide screen
   the tables are read through a slot while the map has room to spare")*. `resize: both` was
   already here and already worked -- it just could not pass 32rem, so dragging did nothing
   in the direction that mattered.

   The CEILING is now the viewport and the STARTING width stays 32rem, set per panel by
   `tfm-panels.place()`. That is the whole change: the default layout is untouched and the
   drag is no longer capped short of the screen.

   **THE PHONE CLAMP IS NOT WEAKENED** (section 4.2) -- it is the same `calc(100vw - 1rem)`
   that was inside the `min()`, now standing alone as the only bound. A panel still cannot
   exceed the viewport, which is what the clamp was for; what it can no longer do is stop at
   32rem on a 1,600 px screen.

   `min-height` is set so a panel dragged to nothing can still be grabbed again -- a resize
   handle on a 0-pixel box is a panel an operator has destroyed by accident. */
/* **THE DEFAULT WIDTH IS THE CONTENT'S, AND THAT IS A REGRESSION OF MINE BEING REPAIRED**
   *(owner, brief 7 section 4.1: a panel is sized to its content, not to the viewport --
   eleven short rows filling the screen edge to edge).*

   Brief 4 needed the panel to resize past 32rem, and I did that by DELETING the 32rem from
   `max-width: min(32rem, calc(100vw - 1rem))`. An absolutely positioned box with `width:
   auto` is shrink-to-fit, and a `.tfm-fields` grid with a `1fr` column has a preferred width
   larger than the space, so it resolved to the max-width -- the whole viewport. **Removing a
   ceiling changed the default, not just the limit**, which is the part I did not check.

   So the two concerns are separated properly this time: `width` sets what it opens at,
   `max-width` sets how far it may be dragged. `resize` writes an inline width that overrides
   the former and is still bounded by the latter, so brief 4's resizing is untouched and
   brief 3's phone clamp is still the floor. `max-content` is the fallback for a browser
   without `fit-content()`; both are content-sized, which is the requirement. */
.tfm-panel { position: absolute; z-index: 30;
             min-width: min(15rem, calc(100vw - 1rem));
             width: max-content;
             width: fit-content(32rem);
             max-width: calc(100vw - 1rem);
             min-height: 4rem;
             max-height: 90vh; overflow: auto; resize: both;
             background: var(--tfm-panel); color: var(--tfm-ink);
             border: 1px solid var(--tfm-edge); border-radius: .6rem;
             box-shadow: 0 8px 28px rgb(0 0 0 / 45%); }
.tfm-panel[hidden] { display: none; }
.tfm-panel > header { display: flex; align-items: center; gap: .5rem;
                      padding: .5rem .7rem; cursor: move; user-select: none;
                      border-bottom: 1px solid var(--tfm-edge);
                      background: var(--tfm-panel-high);
                      border-radius: .6rem .6rem 0 0; position: sticky; top: 0; }
.tfm-panel > header h4 { margin: 0; font-size: .9rem; flex: 1; }
.tfm-panel > header button { padding: .15rem .35rem; line-height: 1; }
.tfm-panel .body { padding: .7rem; }

/* Tabs. ONE definition: the reports page styled these and the map's circuit
   panel needed the same thing, and two copies is how a build ends up with two
   answers to what a selected tab looks like. The formatter marks the live tab
   with aria-selected, so that is what this styles -- what is emitted, not what
   a tab bar usually looks like. */
.tabbar { display: flex; gap: .3rem; flex-wrap: wrap; margin: .2rem 0 .6rem; }
.tabbar button { font: inherit; }
.tabbar button[aria-selected="true"] { border-color: var(--tfm-accent);
                                       color: var(--tfm-accent); }

/* A field list, as the identify popup shows it. */
.tfm-fields { display: grid; grid-template-columns: minmax(7rem, auto) 1fr;
              gap: .3rem .8rem; font-size: .85rem; }
.tfm-fields dt { color: var(--tfm-ink-muted); }
.tfm-fields dd { margin: 0; overflow-wrap: anywhere; }
/* THE PORT LINE UNDER ITS PLACE (brief 5 section 1). Subordinate by weight and indent, so a
   Connectivity list reads as places with a port under each rather than sixteen equal rows.
   Colour is a TOKEN, never a literal: the page is theme-aware and a hard-coded grey is
   invisible on one of the two themes. */
.tfm-fields dt.tfm-sub { color: var(--tfm-ink-muted); font-size: 0.9em; padding-left: 0.6rem; }
.tfm-fields dd.tfm-sub { font-size: 0.9em; }
/* A VALUE THE DOOR COULD NOT NAME reads as a remark, not as data -- it is a sentence about
   what is absent, and it must not be mistaken for the port's name. */
.tfm-fields dd.tfm-unknown { color: var(--tfm-ink-muted); font-style: italic; }

/* The one data table, shared/tfm-table.js. Columns resize from the header cell. */
.tfm-table { border-collapse: collapse; width: 100%; font-size: .85rem; }
/* **A WIDE PANEL MUST NOT PRODUCE A WIDE PAGE** (section 4.1 with 4.2). The table fills the
   panel, and when its columns need more than that the SCROLL happens inside its own wrapper
   rather than pushing the panel -- and therefore the page -- sideways. This is the same rule
   the artifact guidance states for wide content, applied to the one data table. */
.tfm-panel .body > table.tfm-table { display: block; overflow-x: auto; }
.tfm-panel .body > table.tfm-table > tbody,
.tfm-panel .body > table.tfm-table > thead { display: table; width: 100%; }
.tfm-table th, .tfm-table td { text-align: left; padding: .35rem .55rem;
                               border-bottom: 1px solid var(--tfm-edge); }
.tfm-table th { color: var(--tfm-ink-muted); font-size: .72rem; letter-spacing: .04em;
                text-transform: uppercase; white-space: nowrap; }
.tfm-table tbody tr:hover { background: var(--tfm-panel-high); }

/* The metres box under a fault reading (brief 6). Wraps on a phone rather than pushing the
   panel wider -- the panel is already resizable and must not need to be. */
.tfm-ask { display: flex; flex-wrap: wrap; gap: .4rem; align-items: center;
           margin: .6rem 0 .2rem; }
.tfm-ask label { color: var(--tfm-ink-muted); font-size: .85em; flex: 1 1 100%; }
.tfm-ask input { flex: 1 1 6rem; min-width: 0; }

/* The buffer tube heading in the picker's second level (brief 7 section 2.3): a cable holds
   buffers and a buffer holds strands, so the list is broken where the tube changes. */
.tfm-tube { margin: .5rem 0 .25rem; font-size: .75rem; letter-spacing: .02em;
            color: var(--tfm-ink-muted); text-transform: uppercase; }
/* One fibre's colour. **The name is in the `title` as well as the swatch** -- a colour alone
   excludes a colour-blind operator, and Slate against Black is the pair that costs. */
.tfm-fibre-dot { display: inline-block; width: .7rem; height: .7rem; border-radius: 50%;
                 margin-right: .4rem; vertical-align: -1px;
                 border: 1px solid var(--tfm-edge); }
.tfm-fibre-dot[data-color="blue"]   { background: var(--tfm-fibre-blue); }
.tfm-fibre-dot[data-color="orange"] { background: var(--tfm-fibre-orange); }
.tfm-fibre-dot[data-color="green"]  { background: var(--tfm-fibre-green); }
.tfm-fibre-dot[data-color="brown"]  { background: var(--tfm-fibre-brown); }
.tfm-fibre-dot[data-color="slate"]  { background: var(--tfm-fibre-slate); }
.tfm-fibre-dot[data-color="white"]  { background: var(--tfm-fibre-white); }
.tfm-fibre-dot[data-color="red"]    { background: var(--tfm-fibre-red); }
.tfm-fibre-dot[data-color="black"]  { background: var(--tfm-fibre-black); }
.tfm-fibre-dot[data-color="yellow"] { background: var(--tfm-fibre-yellow); }
.tfm-fibre-dot[data-color="violet"] { background: var(--tfm-fibre-violet); }
.tfm-fibre-dot[data-color="rose"]   { background: var(--tfm-fibre-rose); }
.tfm-fibre-dot[data-color="aqua"]   { background: var(--tfm-fibre-aqua); }
