/* Documents step */

/* F1 : the pieces list is a vertical stack, 12px between piece cards. The
   selector is the class the renderer actually emits (.portailetu-documents-list) ;
   the historical .pe-documents-list matched no element, so the stack carried no
   gap at all. */
.portailetu-documents-list {
  display: flex;
  flex-direction: column;
  gap: var(--portailetu-space-3);
}

/* "Tout est transmis, en cours de vérification" notice, sibling of the pieces
   list inside the step wrapper (which carries no box of its own, so the 12px
   that separates it from the list is stated here and equals the list's own
   gap). The SHAPE is the refusal-motif row of a piece (.pe-doc-item__comment) :
   same flex row, same radius / padding / gap tokens, same 16px glyph pinned
   left — no new visual system, only the pair changes. The pair is the accent
   one (a wait, not an error) and is declared LOCALLY, exactly like the piece
   rows do and for the same reason : this addon also renders on the PUBLIC
   campaign page, where extranet.css never loads (MANDATORY §15 autonomy).
   Values mirror the --pe-doc-accent-* pair declared on .pe-doc-item below. */
.pe-doc-notice {
  --pe-doc-accent-surface: #e4f0f8;
  --pe-doc-accent-text:    #1F82C0;
  display: flex;
  align-items: flex-start;
  gap: var(--portailetu-space-2);
  margin-bottom: var(--portailetu-space-3);
  border-radius: var(--portailetu-radius-md);
  padding: var(--portailetu-space-2) var(--portailetu-space-3);
  background: var(--pe-doc-accent-surface);
  color: var(--pe-doc-accent-text);
}

/* 16px, never squeezed, stroke = the inherited text through currentColor. The
   size is restated (the component already emits width/height 16) so a theme
   rule on svg cannot resize it — same guard as the refusal glyph. */
.pe-doc-notice > svg {
  flex: none;
  width: 16px;
  height: 16px;
}

/* Takes the free space and wraps : no ellipsis, no clamp. 13px takes the sm
   token ; the 18px line-height has none, same raw value as the refusal text. */
.pe-doc-notice__text {
  flex: 1;
  min-width: 0;
  font-size: var(--portailetu-text-sm-size);
  line-height: 18px;
}

/* F1 : the main "Documents" card is the SHELL PANEL both surfaces already emit
   around the runner (section.pe-extranet__panel on the extranet, .pe-public__panel
   on the public shell) : #fff, 1px solid #dcdcde, radius 16px and padding 24px are
   already ITS declarations, so none of them is restated here — restating them
   would draw a second frame inside the first. What the panel does not carry is the
   step heading : the runner emits a bare <h3>, left to the theme. Scoped to the
   documents step through the :has() gate so every other step kind keeps its
   current heading. The bottom margin IS the 16px gap between the card header and
   the pieces list (the step wrapper in between has no box of its own). */
.portailetu-workflow-current:has(> .portailetu-documents-step) > h3 {
  margin: 0 0 var(--portailetu-space-4);
  font-size: var(--portailetu-text-lg-size);
  line-height: var(--portailetu-text-lg-line);
  font-weight: var(--portailetu-text-lg-weight);
}

/* F1 : the card title row carries the state summary at its right. The runner
   emits the heading as a bare <h3> and offers no hook inside it, so the row is
   composed from OUTSIDE : the renderer emits the summary as a top-level sibling
   of the step wrapper — a direct child of .portailetu-workflow-current, exactly
   like the <h3> — and the container becomes a two-column grid whose FIRST row
   holds those two. Zero core markup, zero core hook.
   Every OTHER child of the container (the runner's step intro, the step wrapper,
   the step outro) spans both columns and keeps its order in the flow, so the
   vertical rhythm is unchanged : the 16px under the header is still the <h3>'s
   own margin, and the row gap stays 0. Gated by :has() on the summary, so no
   other step kind and no other surface is touched. */
.portailetu-workflow-current:has(> .pe-doc-summary) {
  display: grid;
  grid-template-columns: 1fr auto;
  column-gap: var(--portailetu-space-3);
}

.portailetu-workflow-current:has(> .pe-doc-summary) > * {
  grid-column: 1 / -1;
}

/* Heading half of the title row. min-width: 0 lets a long heading shrink and wrap
   inside its own column instead of pushing the summary out of the card — same
   guard as the piece header's text column. */
.portailetu-workflow-current:has(> .pe-doc-summary) > h3 {
  grid-column: 1;
  grid-row: 1;
  align-self: baseline;
  min-width: 0;
}

/* Summary half : 12/16 meta type, secondary text, tabular figures so the four
   counts keep a fixed advance, one line at desktop width. The 12px gap to the
   heading is the grid's column-gap above. Every value here takes the token that
   already carries it. */
.portailetu-workflow-current:has(> .pe-doc-summary) > .pe-doc-summary {
  grid-column: 2;
  grid-row: 1;
  align-self: baseline;
  color: var(--portailetu-field-label);
  font-size: var(--portailetu-text-xs-size);
  line-height: var(--portailetu-text-xs-line);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

/* Status-tag charte : the four state tags map to ONE meaning per color, using
 * the SAME status pairs the extranet dossier card uses (see the shell status
 * tokens in assets/css/extranet.css). Those shell tokens are scoped to
 * .pe-extranet, and this addon also renders on the PUBLIC campaign page (no
 * .pe-extranet wrapper, no extranet.css loaded) — so the pairs are declared
 * LOCALLY here, on the piece row (the real emitted wrapper), with IDENTICAL
 * values, keeping the addon autonomous (MANDATORY §15) while the parcours
 * red / accent / green / neutral stay the exact same red / accent / green / neutral
 * as the card. Values mirror extranet.css:35,40,65,117-122 — and, for the accent
 * text, the brand --portailetu-primary the shell accent aliases (front.css:2,
 * a hard dependency of this stylesheet). */
.pe-doc-item {
  --pe-doc-neutral-surface: #f0f0f1;
  --pe-doc-neutral-text:    #646970;
  --pe-doc-accent-surface:  #e4f0f8;
  --pe-doc-accent-text:     #1F82C0;
  --pe-doc-ok-surface:      #e2f4e8;
  --pe-doc-ok-text:         #1d7f3b;
  --pe-doc-error-surface:   #fdecea;
  --pe-doc-error-text:      #b32d2e;
  /* F1 frame : radius 12px, padding 16px 20px, and a 10px vertical rhythm
     between the card's own blocks (header row, then the body flow). The 10px
     gap is off the 4/8/12/16/20/24 scale, so it stays a raw value — no token
     carries it and this lot adds none. Border and background already held the
     F1 values (#dcdcde hairline, #fff surface) and are untouched. */
  display: flex;
  flex-direction: column;
  gap: 10px;
  border: 1px solid #dcdcde;
  border-radius: var(--portailetu-radius-lg);
  padding: var(--portailetu-space-4) var(--portailetu-space-5);
  background: #fff;
}

.pe-doc-item__head {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: var(--portailetu-space-3);
}

/* Text column of the header row : takes the free space, may shrink below its
   content (min-width 0 so a long title ellipsises rather than pushing the pill
   out), and holds the title one pixel above its legend. The 1px gap is off the
   spacing scale — raw value, no token. */
.pe-doc-item__title {
  display: flex;
  flex-direction: column;
  gap: 1px;
  flex: 1;
  min-width: 0;
}

/* Piece title. Carried by the <strong> the renderer emits : the browser's bold
   would otherwise win over any weight set on the column. 500 has no token (the
   base type triplet declares 400). */
.pe-doc-item__title > strong {
  font-size: var(--portailetu-text-base-size);
  line-height: var(--portailetu-text-base-line);
  font-weight: 500;
}

.pe-doc-item__legend {
  color: #646970;
  font-size: var(--portailetu-text-xs-size);
  line-height: var(--portailetu-text-xs-line);
}

.pe-doc-item__badge {
  /* Pinned right, never squeezed by the text column (F1 header row), and now on
     the F1 pill metrics : padding 2px 12px, 12/16 type, weight normal (F1
     declares no weight, so the former 600 goes), 999px pill. The horizontal
     padding, the size and the line-height take the tokens that already carry
     those exact values ; the 2px vertical padding is off the 4/8/12/16/20/24
     spacing scale and the weight has no token at the xs role (only xl/lg/md/base
     declare one), so both stay raw values — this lot adds no token. */
  flex: none;
  padding: 2px var(--portailetu-space-3);
  border-radius: var(--portailetu-radius-pill);
  font-size: var(--portailetu-text-xs-size);
  line-height: var(--portailetu-text-xs-line);
  font-weight: 400;
  white-space: nowrap;
}

/* One meaning per color, via the local status tokens above (identical to the
   card's shell status pairs). en attente -> neutral (charte §10 "À fournir"),
   téléversé -> accent (charte §10 "Transmis" : a neutral-positive fact, not an
   alert), validé -> ok, refusé -> error. Soft surface + darker text pair. */
.pe-doc-status--pending {
  background: var(--pe-doc-neutral-surface);
  color: var(--pe-doc-neutral-text);
}
.pe-doc-status--review {
  background: var(--pe-doc-accent-surface);
  color: var(--pe-doc-accent-text);
}
.pe-doc-status--valid {
  background: var(--pe-doc-ok-surface);
  color: var(--pe-doc-ok-text);
}
.pe-doc-status--refused {
  background: var(--pe-doc-error-surface);
  color: var(--pe-doc-error-text);
}

/* Body flow (file link, refusal motif, drop zone) : same 10px rhythm as the one
   the card sets between its own blocks — the former margin-top would have added
   to the card gap. */
.pe-doc-item__body {
  display: flex;
  flex-direction: column;
  gap: 10px;
}

/* Transmitted piece : its upload wrapper renders NOTHING (the picker input is
   clipped, the error line is empty) yet still counts as a flex item of the body
   above, so the 10px gap lands before it and the card ends on that much dead
   space — the only state that pays it. Taking the wrapper out of the flex flow
   removes the gap with it. Out of flow, NOT hidden : no display:none anywhere on
   the input's ancestor chain, the clip technique of .pe-doc-file-input--hidden
   is left untouched, so "Remplacer" still resolves the input (openPicker reads
   it from the .pe-doc-item root) and the data-accept / data-max-mb guards still
   read it from that same root. Gated on the error line being empty : the moment
   a rejected replacement writes into it, :empty stops matching and the wrapper
   returns to the flow, announcing the error on the very same 10px rhythm as
   every other state. Every other state keeps a visible drop zone in that
   wrapper, so this rule never matches them. */
.pe-doc-item[data-status="uploaded"] > .pe-doc-item__body > .pe-doc-item__upload:has(.pe-doc-error:empty) {
  position: absolute;
}

/* F1 file block : the deposited piece's file line is an inset row — sunken
   surface, radius 8px, padding 8px 12px, items centered on one line with an 8px
   gap. Tokens carry every value here (the neutral surface, the md radius, the
   2/3 spacing steps); front.css is a hard dependency of this stylesheet, see the
   enqueue. */
.pe-doc-item__file {
  display: flex;
  align-items: center;
  gap: var(--portailetu-space-2);
  border-radius: var(--portailetu-radius-md);
  padding: var(--portailetu-space-2) var(--portailetu-space-3);
  background: var(--portailetu-neutral-surface);
}

/* Document glyph : 16px, never squeezed, stroke #646970 through the token that
   already carries that exact hue. The size is restated here (the component
   already emits width/height 16) so a theme rule on svg cannot resize it —
   same guard as the drop-zone glyph above. */
.pe-doc-item__file > svg {
  flex: none;
  width: 16px;
  height: 16px;
  color: var(--portailetu-field-label);
}

/* File name : the FRONT accent replaces the admin blue #2271b1 this link
   carried. Direct-child selector so the action links moved into the block keep
   their own colors. 13px takes the sm token ; the 18px line-height has none
   (the scale pairs 13px with 16px), so it stays a raw value — this lot adds no
   token. */
.pe-doc-item__file > a {
  color: var(--portailetu-primary);
  text-decoration: none;
  font-size: var(--portailetu-text-sm-size);
  line-height: 18px;
}

/* Deposit metadata : takes the free space, may shrink below its content, and
   ellipsises on one line rather than wrap the block. */
.pe-doc-item__file-meta {
  flex: 1;
  min-width: 0;
  color: var(--portailetu-field-muted);
  font-size: var(--portailetu-text-xs-size);
  line-height: var(--portailetu-text-xs-line);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* F1 refusal inset : the refusal motif is an inset row on the error pair — soft
   surface + darker text — with the alert glyph pinned left and the text taking
   the free space. Both colors come from the LOCAL error pair declared on
   .pe-doc-item above (the shell equivalents live in extranet.css, which never
   loads on the public campaign page — same autonomy rule as the status tags),
   which RETIRES the raw #d63638 this element carried. Radius, padding and gap
   take the tokens that already carry those exact values. */
.pe-doc-item__comment {
  display: flex;
  align-items: flex-start;
  gap: var(--portailetu-space-2);
  border-radius: var(--portailetu-radius-md);
  padding: var(--portailetu-space-2) var(--portailetu-space-3);
  background: var(--pe-doc-error-surface);
  color: var(--pe-doc-error-text);
}

/* Alert glyph : 16px, never squeezed, stroke = the inherited error text through
   the component's currentColor. The size is restated here (the component
   already emits width/height 16) so a theme rule on svg cannot resize it —
   same guard as the file and drop-zone glyphs. 16px has no token. */
.pe-doc-item__comment > svg {
  flex: none;
  width: 16px;
  height: 16px;
}

/* Motif text : takes the free space, wraps over as many lines as the admin text
   needs — no ellipsis, no clamp, no truncation. 13px takes the sm token ; the
   18px line-height has none (the scale pairs 13px with 16px), so it stays a raw
   value — this lot adds no token. The color is inherited from the row. */
.pe-doc-item__comment-text {
  flex: 1;
  min-width: 0;
  font-size: var(--portailetu-text-sm-size);
  line-height: 18px;
}

/* State prefix. Pinned at 600 : the browser's bold would otherwise land on 700,
   which the charte forbids. 600 has no token at the sm role (only xl/lg/md/base
   declare a weight). */
.pe-doc-item__comment-text > strong {
  font-weight: 600;
}

/* F1 validated inset : twin of the refusal inset above, on the ok pair — soft
   surface + darker text — with the check glyph pinned left and the text taking
   the free space. Both colors come from the LOCAL ok pair declared on
   .pe-doc-item above (the shell equivalents live in extranet.css, which never
   loads on the public campaign page — same autonomy rule as the status tags),
   which RETIRES the raw #1d9e60 this element carried. Radius, padding and gap
   take the tokens that already carry those exact values. */
.pe-doc-item__note {
  display: flex;
  align-items: flex-start;
  gap: var(--portailetu-space-2);
  border-radius: var(--portailetu-radius-md);
  padding: var(--portailetu-space-2) var(--portailetu-space-3);
  background: var(--pe-doc-ok-surface);
  color: var(--pe-doc-ok-text);
}

/* Check glyph : 16px, never squeezed, stroke = the inherited ok text through
   the component's currentColor. The size is restated here (the component
   already emits width/height 16) so a theme rule on svg cannot resize it —
   same guard as the refusal, file and drop-zone glyphs. 16px has no token. */
.pe-doc-item__note > svg {
  flex: none;
  width: 16px;
  height: 16px;
}

/* Note text : takes the free space and wraps rather than truncating. 13px takes
   the sm token ; the 18px line-height has none (the scale pairs 13px with
   16px), so it stays a raw value — this lot adds no token. The color is
   inherited from the row. */
.pe-doc-item__note-text {
  flex: 1;
  min-width: 0;
  font-size: var(--portailetu-text-sm-size);
  line-height: 18px;
}

/* State sentence. Pinned at 600 : the browser's bold would otherwise land on
   700, which the charte forbids. 600 has no token at the sm role (only
   xl/lg/md/base declare a weight). */
.pe-doc-item__note-text > strong {
  font-weight: 600;
}

/* Compact drop zone (F1). The box is the <label> of the file input : it is the
   whole click target and carries the accessible name. Tokens come from
   front.css (a hard dependency of this stylesheet, see the enqueue). Raw values
   below have no token : the 1.5px hairline, the #b7cfe0 dashed hue, the #fafafa
   rest surface, the 7px/10px off-scale rhythm and the 18px line-height (the
   type scale pairs 13px with 16px, not 18px). */
.pe-doc-dropzone {
  display: inline-flex;
  align-self: flex-start;
  max-width: 100%;
  align-items: center;
  gap: 10px;
  border: 1.5px dashed #b7cfe0;
  border-radius: var(--portailetu-radius-md);
  background: #fafafa;
  padding: 7px var(--portailetu-space-3);
  cursor: pointer;
  position: relative;
}

.pe-doc-dropzone:hover {
  border-color: var(--portailetu-primary);
  background: var(--portailetu-accent-surface);
}

.pe-doc-dropzone > svg {
  flex: none;
  width: 16px;
  height: 16px;
  color: var(--portailetu-primary);
}

.pe-doc-dropzone__line {
  min-width: 0;
  font-size: var(--portailetu-text-sm-size);
  line-height: 18px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.pe-doc-dropzone__cta {
  font-weight: 500;
}

.pe-doc-dropzone__browse {
  color: var(--portailetu-primary);
}

.pe-doc-dropzone__meta {
  color: var(--portailetu-field-muted);
}

.pe-doc-file-input--hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  clip-path: inset(50%);
  border: 0;
  opacity: 0;
}

/* Actions of the file block : pinned right (they are the last flex item of a row
   whose metadata takes the free space), never squeezed, never wrapped. Same
   13px/18px as the file name — the 18px line-height stays a raw value. */
.pe-doc-upload-actions {
  flex: none;
  font-size: var(--portailetu-text-sm-size);
  line-height: 18px;
  white-space: nowrap;
}

.pe-doc-upload-actions a {
  color: var(--portailetu-primary);
  text-decoration: none;
}

/* The destructive action alone takes the error hue (F1) ; the other actions keep
   the front accent above. */
.pe-doc-upload-actions .pe-doc-delete {
  color: var(--portailetu-field-error);
}

/* Upload error line (aria-live). Colors and type align to the tokens that
   already carry these values : the LOCAL error text declared on .pe-doc-item
   (retiring the raw #d63638, which was not the charte error red anyway) and
   the xs type pair for the 12px meta size. Layout, markup and behaviour are
   untouched. */
.pe-doc-error {
  color: var(--pe-doc-error-text);
  font-size: var(--portailetu-text-xs-size);
  line-height: var(--portailetu-text-xs-line);
}

@media (max-width: 600px) {
  .pe-doc-item__head {
    flex-direction: column;
    align-items: flex-start;
  }
  .pe-doc-item__badge {
    align-self: flex-start;
  }
  /* Same stack as the piece header above : the title row becomes one column and
     the summary drops UNDER the heading rather than squeeze it. The 16px that
     separates the header from the pieces list moves from the heading to the
     summary, now the last element of the stacked header — same total rhythm, no
     gap inserted between the heading and its summary. */
  .portailetu-workflow-current:has(> .pe-doc-summary) {
    grid-template-columns: 1fr;
  }
  .portailetu-workflow-current:has(> .pe-doc-summary) > h3 {
    margin-bottom: 0;
  }
  .portailetu-workflow-current:has(> .pe-doc-summary) > .pe-doc-summary {
    grid-column: 1;
    grid-row: 2;
    margin-bottom: var(--portailetu-space-4);
  }
}

