/* THE CLIENT-FACING CHROME.
 *
 * One stylesheet for every page a person who is NOT the studio's owner can reach: the client portal's
 * doors and its signed-in pages, the signing pages, the public form's thank-you and closed pages, the
 * client galleries, and the payment confirmation. It replaces two inline `<style>` blocks that used to
 * live inside `templates/plain_base.html` and `templates/portal/base.html`, which is what the rule
 * against hand-typed values in a page is for: a value written in a template cannot be found, compared or
 * changed. The rules are the same rules, moved; the two blocks are gone.
 *
 * Values come from a token or from Bloom's own vendored sheet (`static/css/bloom-tokens.css`, linked
 * ahead of this file by both shells). Nothing here is a new colour or radius invented for this file.
 *
 * The portal's own door pages were measured against Bloom's client portal, read live and PUBLICLY on
 * 4 November 2026 at 1280 wide, which is what makes them measurable at all: their sign in door at
 * https://ww3.traetongarlphotography.com/login and their forgotten-password door at
 * https://ww3.traetongarlphotography.com/password-reset. Their numbers, not mine:
 *
 *   the page      white, Work Sans 14/21, black
 *   the shell     a centred column padded 80 / 24 / 48 (and 120 at the foot on the password door)
 *   the mark      capped at 208 x 72, and at 208 x 48 on the password door
 *   the heading   24/28 in their Medium cut, 96px below the mark (80px on the password door)
 *   the sentence  14/21, 12px below the heading
 *   the form      48px below, 768 wide on the sign in door and 384 on the password door, a 24px gap
 *   a field       372 x 44 on the sign in door (384 x 44 there), a 1px rgba(0,0,0,.15) hairline on a
 *                 4px corner, a borderless input padded 16px, a label at 16px / 21px held at opacity 0,
 *                 and a placeholder in rgba(0,0,0,.5)
 *   the quiet link  #888, 24px under the fields
 *   the submit     104 x 44 in #333333, white 14/20 in their Medium cut, on a 4px corner
 *   the line under it  #888, 48px below the button
 *
 * Bloom's own badge ("Powered by bloom") is their marketing, not reproduced, exactly as their badge
 * panel on Settings > Client Portal was not.
 */

/* The studio's palette, stated once for the client sheets. The workspace carries the same names inside
   `templates/base.html`; a client page does not extend the workspace shell, so it needs its own copy of
   the handful it uses. Two copies of a palette, not two copies of a design. It also holds the two values
   Bloom's own token sheet does not carry and these sheets need by name rather than by number: the pill
   radius, and the shadow under their dark CTA which was read off their live client door (rgb(51, 51, 51)
   with rgba(51, 51, 51, .25) 0 4px 12px beneath it). */
:root {
  --accent: #FF325A;
  --accent-fg: #FFFFFF;
  --ink: #000000;   --paper: #FFFFFF;  --wash: #F2F2F2;  --line: #EDEDED;   --edge: #E3E3E3;
  --muted: #888888; --done: #6EC250;   --paused: #F5A623; --started: #2F80ED; --none: #C9CCD1;
  --danger: #D92B4B; --tint: #FFF0F3;
  /* Bloom's five project statuses, off its own status editor on 7 November 2026: the pill on the All
     Projects list and the job dot on the lists that show one. Declared once in bloom-tokens.css, which
     this sheet is always served after, and referenced here rather than typed a second time. */
  --st-pending: var(--color-status-pending); --st-booked: var(--color-status-booked);
  --st-processing: var(--color-status-processing);
  --st-completed: var(--color-status-completed); --st-canceled: var(--color-status-canceled);
  --radius-pill: 999px;
  --shadow-cta: 0 4px 12px rgba(var(--color-cta-dark-ink), .25);
}

/* the page surface a door sits on: Bloom's own doors are white, not the studio's wash. The portal's own
   type stack, ink and headline size are his Client Portal styling options, which is why they are read
   here as variables rather than fixed. */
.bloom.pt-body { background: var(--color-background-white);
                 font-family: var(--portal-font, var(--font-regular));
                 color: var(--portal-ink, var(--color-text-body)); }

/* ---- the two shared shells ---- */

body {
  margin: 0;
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  font-size: 16px;
  line-height: 1.55;
  background: var(--wash);
  color: var(--ink);
}

/* the band a client-facing page wears: the mark, the studio's name, and a quiet right-hand side */
.bar { padding: 16px 26px; background: var(--accent); color: var(--accent-fg); }
.bar img { max-height: 42px; vertical-align: middle; margin-right: 12px; }
.bar strong { font-weight: 700; }

main { max-width: 760px; margin: 30px auto; padding: 0 18px; }
footer { text-align: center; color: var(--muted); font-size: 12px; padding: 24px 0 40px; }

.card { background: var(--paper); border: 1px solid var(--line); border-radius: var(--radius-lg);
        padding: 22px 24px; margin-bottom: 18px; }
h1 { font-size: 24px; font-weight: 400; margin: 0 0 14px; }
/* The portal's own headings. SCOPE IS `body.bloom.pt-body`, NOT `.bloom`: the two payment confirmation pages
   (`billing/invoice_paid.html`, `portal/paid.html`) wear `bloom` on a root DIV without being portal chrome,
   and a bare `.bloom h2` here was leaking onto them - the client and job names came out at 500 where
   Bloom's own paid page computes 400 and this studio's own `.bloom h2 { font-weight: 400 }` says so. Found
   by the billing family capture sweep on 5 November 2026, which re-took the paid page and saw the two
   weights move. The comment used to claim the scoping stopped exactly this. */
body.bloom.pt-body h2 { font-size: 18px; font-weight: 500; }
body.bloom.pt-body h3 { font-size: 15px; font-weight: 500; }
table { width: 100%; border-collapse: collapse; }
th, td { text-align: left; padding: 9px 10px; border-bottom: 1px solid var(--wash); vertical-align: top; }
.pill { display: inline-block; padding: 2px 10px; border-radius: var(--radius-pill); background: var(--wash); font-size: 12px; }
.btn { display: inline-block; background: var(--accent); color: var(--accent-fg); padding: 10px 16px;
       border-radius: var(--radius-sm); text-decoration: none; border: 0; cursor: pointer; }
.btn.ghost { background: var(--paper); color: var(--ink); border: 1px solid var(--edge); }
.muted { color: var(--muted); }
pre.doc { white-space: pre-wrap; font: 13px/1.6 ui-monospace, Menlo, monospace; background: var(--wash);
          border: 1px solid var(--line); padding: 16px; border-radius: var(--radius-lg); }
.msg { padding: 11px 14px; border-radius: var(--radius-sm); background: var(--color-background-light-grey);
       margin-bottom: 14px; }
.cover { width: 100%; display: block; max-height: 230px; object-fit: cover; }
.grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 18px; }
@media (max-width: 720px) { .grid { grid-template-columns: minmax(0, 1fr); } }

/* the list a client's projects arrive in on the portal home */
.table { width: 100%; border-collapse: collapse; background: var(--paper);
         border: 1px solid var(--line); border-radius: var(--radius-lg); }
.table th { font-size: 11px; text-transform: uppercase; letter-spacing: .08em; color: var(--muted);
            text-align: left; padding: 11px 14px; border-bottom: 1px solid var(--wash); }
.table td { padding: 12px 14px; border-bottom: 1px solid var(--line); }

/* ------------------------------------------------------------------- the portal's centred door column */

.bloom .pt-shell {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  min-height: 100vh; width: 100%; padding: 80px 24px 48px;
  max-width: none; margin: 0; box-sizing: border-box;
}
/* the password door carries 120px of foot where the sign in carries 48. Their own column is still
   centred in what is left, which is what their computed `justify-content: center` says on that page: only
   the foot differs */
.bloom .pt-shell.pt-top { padding-bottom: 120px; }

.bloom .pt-logo-box { display: inline-block; }
.bloom .pt-logo { display: block; max-width: 208px; max-height: 72px; width: auto; height: auto; }
.bloom .pt-shell.pt-top .pt-logo { max-height: 48px; }

/* a page with no mark at all falls back to the studio's name rather than an empty box */
.bloom .pt-name { font-family: var(--font-medium); font-size: 18px; line-height: 24px; color: var(--color-text-body); }

.bloom .pt-heading { margin: 96px 0 0; text-align: center; font-family: var(--font-medium); font-size: var(--headline, 24px);
                     line-height: 28px; font-weight: 400; color: var(--portal-ink, var(--color-text-body)); }
.bloom .pt-shell.pt-top .pt-heading { margin-top: 80px; }
.bloom .pt-lede { margin: 12px 0 0; text-align: center; font-size: 14px; line-height: 21px; color: var(--color-text-body); }

.bloom .pt-form { display: flex; flex-direction: column; align-items: center; gap: 24px;
                  width: 100%; max-width: 768px; margin-top: 48px; }
.bloom .pt-form.pt-narrow { max-width: 384px; }

.bloom .pt-grid { display: grid; grid-template-columns: minmax(0, 1fr); gap: 24px;
                   width: 100%; max-width: 100%; }
@media (min-width: 768px) {
  .bloom .pt-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

.bloom .pt-field { position: relative; display: block; width: 100%; height: 44px; cursor: pointer;
                   padding: 0; margin: 0;
                   border: 1px solid var(--color-border-black-15); border-radius: var(--radius-sm); }
.bloom .pt-input {
  width: 100%; height: 44px; padding: 0 16px; border: 0; background: transparent;
  font-family: var(--font-regular); font-size: 14px; line-height: 20px; color: var(--color-text-body);
  border-radius: var(--radius-sm); appearance: none; outline: none; box-sizing: border-box;
}
.bloom .pt-input::placeholder { color: var(--color-text-black-50); }
/* THEIR FLOATING LABEL, both of its states, read off their own field on 4 November 2026: at rest 14/20 at
   50% of the field, at opacity 0, with the placeholder carrying the word; once the field has content 12/16
   at the field's top edge, pulled half its own height up over the hairline, at opacity 1. `placeholder-shown`
   is the same switch their own `peer-placeholder-shown:` variants use, and their transition is 150ms. */
.bloom .pt-label { position: absolute; left: 16px; top: 0; z-index: 10; max-width: calc(100% - 20px);
                   font-size: 12px; line-height: 16px; color: var(--color-text-black-50); cursor: text;
                   transform: translateY(-50%); opacity: 1; transition: all .15s; pointer-events: none; }
.bloom .pt-field .pt-input:placeholder-shown + .pt-label { top: 50%; font-size: 14px; line-height: 20px;
                                                           opacity: 0; }

.bloom .pt-quiet { color: var(--color-text-grey); font-size: 14px; line-height: 21px; text-decoration: none; }
.bloom .pt-quiet:hover { text-decoration: underline; }

.bloom .pt-submit {
  display: inline-flex; align-items: center; justify-content: center; position: relative; margin-top: 24px;
  min-width: 104px; height: 44px; padding: 0 16px; border: 0; border-radius: var(--radius-sm);
  background: rgba(var(--color-cta-dark-ink), 1); color: var(--color-text-white);
  box-shadow: var(--shadow-cta);
  font-family: var(--font-medium); font-size: 14px; line-height: 20px; cursor: pointer; text-decoration: none;
}
.bloom .pt-submit-word { display: flex; align-items: center; justify-content: center; gap: 8px;
                         white-space: nowrap; }

.bloom .pt-nav { margin-top: 24px; text-align: center; color: var(--color-text-grey); font-size: 14px; line-height: 21px; }
.bloom .pt-nav a { color: var(--color-text-grey); }

.bloom .pt-msg { margin: 0 0 16px; padding: 11px 14px; border-radius: var(--radius-sm);
                 background: var(--color-background-light-grey); font-size: 14px; line-height: 21px;
                 color: var(--color-text-body); }
.bloom .pt-error { background: var(--tint); color: var(--danger); }

.bloom .pt-foot { margin: 0; padding: 0; color: var(--color-text-grey); font-size: 12px; line-height: 16px;
                  text-align: center; }

/* ------------------------------------------------------------------- the portal once a client is in */
/* OURS, AND NAMED AS OURS. Bloom's signed-in client portal has no public page - the dashboard a client
   sees sits behind a client sign in this studio has no account for - so the band, the projects table and
   the tiles below are this studio's own design, not a measured copy of theirs. What IS measured is the
   vocabulary they are built from: the same field, the same submit, the same 4px corner and the same
   hairlines the two public doors established (`parity/portal-signin-table.txt`,
   `parity/portal-forgot-table.txt`), which is the "same column, same field, same submit" rule. */

/* the cover art and the studio's name as a band under it */
.bloom .pt-cover { display: block; width: 100%; height: auto; max-height: 340px; object-fit: cover; }

.bloom .pt-bar { display: flex; align-items: center; justify-content: space-between; gap: 16px;
                 padding: 14px 26px; background: var(--accent); color: var(--accent-fg); }
.bloom .pt-bar-mark { display: flex; align-items: center; gap: 12px; min-width: 0; }
.bloom .pt-bar img { display: block; max-height: 42px; }
.bloom .pt-bar-name { font-family: var(--font-medium); font-size: 16px; line-height: 21px; }
.bloom .pt-bar-who { display: flex; align-items: center; gap: 16px; font-size: 14px; line-height: 21px;
                     opacity: .9; white-space: nowrap; }
.bloom .pt-bar-who a { color: var(--accent-fg); }

/* the client's own column: the doors' measure, opened out for a page with content on it */
.bloom .pt-main { max-width: 900px; margin: 0 auto; padding: 32px 24px 72px; }

.bloom .pt-greet { margin: 0 0 24px; }
.bloom .pt-greet-title { margin: 0 0 8px; font-family: var(--font-medium); font-size: var(--headline, 24px);
                         line-height: 1.3; font-weight: 400; color: var(--portal-ink, var(--color-text-body)); }
.bloom .pt-greet-body { margin: 0; font-size: 14px; line-height: 21px; white-space: pre-wrap; }

.bloom .pt-card { background: var(--color-background-white); border: 1px solid var(--color-border);
                  border-radius: var(--radius-lg); padding: 24px; margin: 0 0 24px; }
.bloom .pt-card-title { display: block; margin: 0 0 12px; font-family: var(--font-medium); font-size: 16px;
                        line-height: 21px; color: var(--color-text-body); }

.bloom .pt-section { margin: 0 0 12px; font-family: var(--font-medium); font-size: 18px; line-height: 24px;
                     font-weight: 400; color: var(--color-text-body); }

/* the doors' one field, in its multi-line cut: same hairline, same 4px corner, same 14/21 input */
.bloom .pt-field.pt-field-area { height: auto; min-height: 104px; }
.bloom .pt-input.pt-input-area { height: auto; min-height: 102px; padding: 12px 16px; resize: vertical;
                                 line-height: 21px; }
.bloom .pt-write-actions { display: flex; flex-wrap: wrap; gap: 12px; margin-top: 20px; }
.bloom .pt-write-actions .pt-submit { margin-top: 0; }
/* the optional second button, on the submit's own box but quiet: the studio's accent, not their black */
.bloom .pt-submit.pt-submit-ghost { background: var(--accent); color: var(--accent-fg); box-shadow: none; }

/* the projects table */
.bloom .pt-table { width: 100%; border-collapse: collapse; background: var(--color-background-white);
                   border: 1px solid var(--color-border); border-radius: var(--radius-lg);
                   overflow: hidden; }
.bloom .pt-table th { font-size: 12px; line-height: 16px; text-transform: uppercase; letter-spacing: .06em;
                      color: var(--color-text-grey); text-align: left; padding: 12px 16px;
                      border-bottom: 1px solid var(--color-border); white-space: nowrap; }
.bloom .pt-table td { font-size: 14px; line-height: 21px; padding: 14px 16px;
                      border-bottom: 1px solid var(--color-border); vertical-align: top; }
.bloom .pt-table tr:last-child td { border-bottom: 0; }
.bloom .pt-table a { color: var(--portal-ink, var(--color-text-body)); }
.bloom .pt-state { display: inline-block; padding: 2px 10px; border-radius: var(--radius-pill);
                   background: var(--color-background-light-grey); font-size: 12px; line-height: 18px; }
.bloom .pt-quietline { font-size: 13px; line-height: 20px; color: var(--color-text-grey); }
.bloom .pt-balance { margin: 16px 0 0; font-size: 14px; line-height: 21px; }
.bloom .pt-empty { margin: 0; font-size: 14px; line-height: 21px; color: var(--color-text-grey); }

/* a job's own pieces */
.bloom .pt-note { margin: 0; font-size: 14px; line-height: 21px; white-space: pre-wrap; }
.bloom .pt-doc { white-space: pre-wrap; font-family: var(--font-mono); font-size: 13px; line-height: 1.6;
                 background: var(--color-background-light-grey); border: 1px solid var(--color-border);
                 padding: 16px; border-radius: var(--radius-sm); margin: 8px 0; }
.bloom .pt-tiles { display: grid; grid-template-columns: repeat(auto-fill, minmax(180px, 1fr)); gap: 16px; }
.bloom .pt-tile { display: block; border: 1px solid var(--color-border); border-radius: var(--radius-lg);
                  background: var(--color-background-white); overflow: hidden;
                  text-decoration: none; color: inherit; }
.bloom .pt-tile img { display: block; width: 100%; height: 130px; object-fit: cover;
                      background: var(--color-background-light-grey); }
.bloom .pt-tile-name { padding: 10px 12px 2px; font-size: 14px; line-height: 21px; }
.bloom .pt-tile-meta { padding: 0 12px 12px; font-size: 12px; line-height: 18px; color: var(--color-text-grey); }
.bloom .pt-actions { display: flex; flex-wrap: wrap; gap: 12px; align-items: center; }

/* ------------------------------------------------------------------- the client's own progress strip */
/* A square per step of a job's workflow, on the client's own job page (templates/portal/project.html), so a
 * client sees where their job has got to at a glance. It is HIS ask (his point 3 of 3 November) and it is
 * OURS, AND NAMED AS OURS: **Bloom's own client job page was read live and read-only for this unit** - signed
 * in as him at 1280 wide on 5 November 2026, on two of the three projects he holds, through their own View
 * Portal preview at `app.bloom.io/client-project/<id>` - and it draws no workflow strip at all. The sections their
 * client page does draw are the cover band, the title, Send message, the contact card, Activity, Messages,
 * Billing, Contracts, Project Files and Project Notes. So there is nothing of theirs to be held to here and
 * no parity table is claimed for this block, which is why the arrangement is this studio's own.
 *
 * What IS theirs, and is used exactly as measured: the four step labels and their four colours, read off his
 * own account's workflow board on 31 October 2026 (green done, blue under way, amber held, grey nothing yet).
 * They are the `--done`, `--started`, `--paused` and `--none` tokens this sheet already carries, so the
 * square's ink is a token selected by the label's own class, never a value typed into markup - a client page
 * here carries no `style` attribute at all, and the four classes are what keeps it that way.
 *
 * The caption under each square is the step's own name, and the line beneath the row counts what is done.
 * Sizes are multiples of `--spacing` and nothing here is a colour, a radius or a shadow of its own. */
.bloom .pt-strip { display: flex; flex-wrap: wrap; gap: calc(var(--spacing) * 4); margin: 0; padding: 0;
                   list-style: none; }
.bloom .pt-step { display: flex; flex-direction: column; align-items: center; gap: calc(var(--spacing) * 2);
                  min-width: calc(var(--spacing) * 16); }
.bloom .pt-step-square { display: block; width: calc(var(--spacing) * 6); height: calc(var(--spacing) * 6);
                         border-radius: var(--radius-sm); background: var(--none); }
.bloom .pt-step-name { font-size: var(--font-size-xs); line-height: calc(16 / 12); text-align: center;
                       color: var(--color-text-grey); max-width: calc(var(--spacing) * 24); }
.bloom .pt-step-done .pt-step-square { background: var(--done); }
.bloom .pt-step-started .pt-step-square { background: var(--started); }
.bloom .pt-step-paused .pt-step-square { background: var(--paused); }
.bloom .pt-strip-count { margin: calc(var(--spacing) * 4) 0 0; }

/* The way back to the client's own project list, at the head of their one job page. It had none: a client who
   opened a job could sign out or press their browser's back button and nothing else. Ours, and named as ours -
   Bloom's own client page puts the studio's mark where its own navigation belongs, and this studio's portal
   keeps the client's list one click away instead. Quiet type, no colour of its own. */
.bloom .pt-back-line { margin: 0 0 calc(var(--spacing) * 4); }
.bloom .pt-back { font-size: var(--font-size-sm); line-height: calc(21 / 14); color: var(--color-text-grey); }

/* ------------------------------------------------------------------- THE SIGNING PAGES */
/* `/sign/<token>/` and its thank-you page: the two public pages a client signs a contract or a usage
 * licence on, in licensing/sign.html and licensing/signed.html.
 *
 * NO PARITY TABLE IS CLAIMED FOR EITHER, and that is the finding rather than a shortcut: Bloom's signing
 * page lives behind a client contract link inside their own client portal, and this studio holds no such
 * token, so their version of this moment has never been mounted at a recorded viewport and there are no
 * numbers of theirs to be held to. What the two pages DO wear is the vocabulary the studio's own client
 * doors established and measured on 4 November 2026 (parity/portal-signin-table.txt and
 * parity/portal-forgot-table.txt): the white ground the client sheet paints its pages on, `.pt-field`'s
 * 44px on its 1px rgba(0, 0, 0, .15) hairline and its 4px corner, and `.pt-submit`'s black 104 x 44. Only
 * what is these two pages' own is written below. No colour, radius or shadow is typed in it: every value is
 * a token or a multiple of `--spacing`, except the two unitless line-height ratios carried over from the
 * portal's own doors. That is the same rule the workspace's own page blocks are held to.
 *
 * The document itself is `.pt-doc`, the studio's document box, rather than a second copy of it: a licence's
 * wording and a contract's are the same block of text, and the portal's signed-in job page already draws
 * them with that class.
 */
.bloom .sg-shell { max-width: calc(var(--spacing) * 192); margin: 0 auto;
  padding: calc(var(--spacing) * 12) calc(var(--spacing) * 6) calc(var(--spacing) * 18); }
.bloom .sg-panel { background: var(--color-background-white); border: var(--border-regular);
  border-radius: var(--radius-lg); padding: calc(var(--spacing) * 12); }
/* the document's own name, at the head of the panel under the studio's mark: their 24 on 28 in the Medium
   cut, which is the size Bloom's own client doors give a heading */
.bloom .sg-title { margin: calc(var(--spacing) * 12) 0 0; font-family: var(--font-medium);
  font-size: calc(var(--spacing) * 6); line-height: calc(28 / 24); font-weight: 400;
  color: var(--color-text-body); }
.bloom .sg-lede { margin: calc(var(--spacing) * 3) 0 0; font-size: var(--font-size-sm);
  line-height: calc(21 / 14); color: var(--color-text-body); }
.bloom .sg-words { margin: calc(var(--spacing) * 6) 0 0; }
/* the signature block: the doors' two fields, the tick, their own submit and the evidence line */
.bloom .sg-fields { margin-top: calc(var(--spacing) * 6); }
.bloom .sg-agree { display: flex; align-items: flex-start; gap: calc(var(--spacing) * 3);
  margin: calc(var(--spacing) * 6) 0 0; font-size: var(--font-size-sm); line-height: calc(21 / 14);
  color: var(--color-text-body); cursor: pointer; }
.bloom .sg-tick { flex: none; width: calc(var(--spacing) * 4); height: calc(var(--spacing) * 4);
  margin: calc(var(--spacing) / 2) 0 0; accent-color: var(--accent); }
.bloom .sg-sign-btn { margin-top: calc(var(--spacing) * 6); }
.bloom .sg-evidence { margin: calc(var(--spacing) * 3) 0 0; font-size: var(--font-size-xs);
  line-height: var(--line-height-hint); color: var(--color-text-grey); }
/* the already-signed state: the state pill and the line that names who signed and when */
.bloom .sg-signed { margin: calc(var(--spacing) * 6) 0 0; }
.bloom .sg-signed-line { margin: calc(var(--spacing) * 3) 0 0; }
.bloom .sg-contact { margin: calc(var(--spacing) * 6) 0 0; }
