Making the body a column to keep the footer at the bottom shrank every
block centred with auto margins (the account area, and two of the Site's
sections) to the width of its content. They take the full width again, up
to their max-width, exactly as before.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
On a short page (sign-in, an empty cart) the footer followed the content
and the rest of the screen was left blank below it, more so with the Site
drawn at 80%. The body is now a column at least the screen's height with
the footer pushed to its end; under the 80% zoom that height is 125vh,
because the zoom scales viewport units too.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The order page becomes the customer's area, one page at four addresses:
- /conta/entrar: sign in or create an account, side by side. "Esqueci
minha senha" points to the Dropstar WhatsApp until e-mail can be sent.
- /conta: the counts of orders waiting for payment, in production, in
correction and finished, and the latest one.
- /conta/pedidos: every order and the cart waiting for payment in one list,
newest first, filtered by group, order number and period, ten per page.
The cart shows "Aguardando pagamento" and its "Pagar" goes to the PIX
page when a PIX code is open. An order opens in place with its progress,
items, delivery, history, files and the correction form. A guest sees
the orders paid in this browser.
- /conta/dados: WhatsApp and a saved delivery address (the CNPJ is locked),
e-mail and password changes, both confirmed with the current password;
a password change signs the other devices out.
The cart fills in the account's details and saved address. New API routes
for the details, and the order list takes filters and pages and returns
the counts; only the newest unpaid quote whose files still exist is listed.
The Site's "Minha conta" and "Ver meus pedidos" point to the new addresses.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
"Meus pedidos" was still the prototype's plain page. It now has the Site's
stripe, header and footer, and its type, colours and cards: each order shows
its status, a progress line through production (or the correction the team
asked for), the items with metres and price, where it goes, and on request
the history, the files to download and the correction form. Carts waiting
for payment are listed with a button to pay. Sign-in and account creation
are side by side.
The header, stripe, menu, footer and tokens moved from index.html's inline
style to site-shell.css, which both pages load. The header's search box,
which did nothing, is gone.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The text sizes were chosen looking at the Site with the browser at 80%; at
100% everything felt too big. On screens 1100 px and wider the Site is now
drawn at 80% (CSS zoom); phones and tablets keep their sizes. The time left
while reading a large file shows the seconds under 10 s ("faltam 7 s")
instead of "quase pronto".
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Reading a large PNG in the browser for its preview showed "gerando a
prévia… 87%". It now shows the time left, worked out from how long the
reading has taken so far: "faltam cerca de 25 s", "faltam cerca de 3 min",
"quase pronto". The bar still fills as it goes.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The product page's notice about the upload time is gone. The cart's upload
bar now reads "Enviando seus arquivos · faltam cerca de 6 min", measured
from the upload's own speed (a range from the size for the first seconds),
with a line saying the time depends on the internet and to keep the page
open. The header and the pay button show the same time instead of a
percentage.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The notice stayed on the product page after the item went to the cart,
showing the last file's size on the next order. It is now redrawn wherever
the files are cleared and hidden when no product is open. The text is one
line: "Envio: até 8 min (501,2 MB), conforme sua internet. Mantenha a
página aberta."
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Removes "Complete o endereço de entrega para ir ao pagamento." The required
fields (CNPJ, WhatsApp, e-mail, and the delivery address except the
complement) carry a red asterisk, and aria-required for screen readers.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Each cart item has a checkbox and a thumbnail of its first file (or its
extension when there is none). Only checked items are priced, quoted,
uploaded and paid; an unchecked item stays in the cart, dimmed, for a later
order, and stays there after the others are paid. The header count is the
whole cart; the summary counts what is being paid.
Also removes the "A conta nasce aqui…" and "Carrinho salvo neste
navegador…" texts.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Every Site text size up to 18 px grows another pixel, the Kanban's up to
14 px half a pixel, and the icons one pixel. The pay button grows to two
lines when "Pagar os N itens de uma vez" no longer fits on one.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Most of the text was 11 to 13 px and hard to read. Every size up to 16 px
grows: by 1.5 px up to 12.5, 1 px up to 14 and 0.5 px up to 16 on the Site,
and a little less on the denser Kanban. Headings and prices keep their size.
Icons grow by 2 px so they stay in proportion with the text beside them.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Buttons: add to cart (bag with plus), go to payment (lock), remove from
the cart (bin).
- Delivery: a pin for pickup in Franca, a truck for home delivery.
- Payment: card and QR code on the methods, copy on the PIX code, a clock on
its countdown, a check on the confirmation.
- Status: a check when the files are sent, check, alert, redo and cross in
the quality list instead of Unicode symbols, and a check on finished steps.
- Kanban: a truck or pin for where an order goes, a speech bubble on the
WhatsApp link, a download arrow on the file buttons.
All Lucide shapes drawn inline, as in the header.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The header's search, account and cart get icons, with the item count on the
cart instead of "Carrinho (N)"; on phones only the icons show. The upload
zone, remove, rotate and mirror buttons used Unicode symbols that look
different, or are missing, depending on the system's fonts; they are now
Lucide icons (ISC licence) drawn inline, so nothing new is loaded and the
CSP is unchanged.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Above 150 MB the browser cannot read JPG or WebP in parts, so a large
artwork was refused. It is now measured from its header, graded and priced
with the discount like any other, and placed on the sheet as a full box,
which is exact for JPG. The card says there is no preview and that the team
checks the art before printing.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
When files are picked, the product page shows the range the upload takes
between a slow (10 Mbps) and a fast (150 Mbps) connection, and asks to keep
the page open. The cart shows the same range until the real speed is
measured, then the measured time left.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The browser put the CNPJ, WhatsApp, e-mail, CEP and address back after a
reload without telling the page, which then showed them but could not pay
until they were typed again. The fields are now emptied on load and marked
autocomplete="off", and the saved cart holds only the items: the details and
address are typed again after a reload or a closed tab. The payment page
already takes them from the server.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A backup service runs pg_dump every day at 03:00 Brasília, checks the archive,
encrypts it with age to a public key and uploads it with a token for that
bucket only. The server cannot read or delete backups: the private key stays
with the owner, the bucket's lifecycle rule expires copies and its lock stops
early deletion. Each run is recorded and shown on the Kanban's Integrations
tab. tests/backup_test.py backs up, restores into a scratch database and
compares the rows in CI. Setup and restore: docs/BACKUP.md.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Each artwork gets the same card as a finished sheet: "Suas artes" with the
count of artworks and copies, a thumbnail, the size in cm with pixels,
format and weight, a DPI chip and how many fit per row, the resolution or
width hint, then width in cm, a copies stepper, rotate and mirror, and the
usual sizes. Packing, pricing and the hints are unchanged.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Opening a question moved its link out of the row into the answer, and only
that heading closed it again. The four questions are now a row of links
that always stays: the open one is highlighted, its answer shows below,
another link switches to its answer and the same link closes it.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The product page is rebuilt around mockup 1. The two ways to send are
cards under the title; the PNG/CDR route choice is gone (it never changed
the price, and the picker now takes every allowed format). Each file card
has a thumbnail, its size, check chips with a plain sentence for any
problem, a "Ver detalhes da conferência" link and a copies stepper; a CDR
file says "Conferência manual · preço cheio" and asks for the length. The
buy box shows the price scale in DPI with the customer's step, the metre
and 10 cm length, the total and what the resolution saved, and "Sai em N
partes" only above 20 m. Folha já montada gets "Ampliar" instead of zoom.
Pricing, grade and checks are unchanged.
Fixes on top: the card thumbnail is a small image made once, not the full
preview re-parsed on every repaint; sizes from 1 GB up read in GB; a failed
upload is shown with "Tentar de novo" instead of retrying silently on every
cart change. The browser suites wait for the product and the reloaded page
instead of racing them, and the artwork suite delays imagemDaArte, which
the packing now uses, fixing the CI failure of f4aacb5.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Artes avulsas decoded every file whole, and the packing decoded each one
again on every repaint, so a large artwork failed to load. A PNG over 150
MB is now measured from its header (pixel size, so DPI and grade stay
exact) and packed from a 1200-pixel copy read as a stream, with progress on
its card; every artwork's image is loaded once and reused by the packing.
A large JPG or WebP asks for a PNG, and the grade card no longer calls a
file unreadable while it is still being read.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Reading a large sheet repainted the list and "Sua folha" on every progress
step, so the preview flickered; progress now moves the bar in place and
"Sua folha" shows a skeleton until the preview is ready. A sheet printed
N times is shown N times (up to six, then a count). The payment page shows
skeletons while the order loads and until the card form is ready.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Uploads of several GB ran behind one grey line in the cart. The order
summary now has a progress bar with the percentage, size and an estimate of
the time left from the recent speed; the header shows "enviando 45%" on
every page while it runs; the payment button says what it is waiting for;
and leaving the page mid-upload asks first.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A large sheet had no preview and no automatic check of pieces, residue,
gaps and background, because decoding it whole would crash the browser.
A PNG over 150 MB is now inflated as a stream (DecompressionStream) and
unfiltered row by row, keeping every n-th pixel: a 600-pixel-wide copy in
about 100 MB of memory whatever the file's size (6.6 s for 500 MB, 22.7 s
for 2.4 GB of random pixels, identical to Pillow's output for RGB, RGBA,
grey, grey+alpha, palette and 16-bit). The copy is the preview and what
the sheet check reads; the grade still comes at once from the header.
The preview note promising a server-side re-nesting that does not exist
is removed.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Without an approved card payment there was no way to try the board, the
files and the print flow in production. "Criar pedido de teste" on an
approved quote creates the order through the same path as a paid one, marked
TESTE on its card and panel and audited; neither it nor its stage moves
queue anything for Tiny or WhatsApp.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Without access to the Mercado Pago panel, "Verificar conta" now also says
how many payment notifications arrived and passed the signature in the last
24 hours, how many were refused by it, and the last one received: the PIX
payments created in test mode notify the webhook, so this shows whether
Mercado Pago reaches the server.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
"Verificar conta" on the Mercado Pago card of the Integrations tab runs the
read-only account check (whether the token is a test user's, the card
methods, how the test card is classified) without a container console.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The rule sizing the PIX code field applied to every input in the payment
area, turning the card form's instalment radios into tall boxes; the
heading rule likewise reached the form's own headings. Both now apply only
to the page's own elements.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A credit card payment with the test credentials was refused with 10113
("the payment method is excluded by a rule"). Every card was sent with
three_d_secure_mode, which only debit needs, and with the order's CNPJ as
payer instead of the cardholder's document from the card form. Debit
methods keep 3-D Secure, and the card form's document is the payer.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Sheets of several GB are the normal order. The upload limit is now 5 GB.
ClamAV scans files up to 2 GB; a larger file is released only when its
first bytes match the format its name claims, and a disguised file is
refused. The Site grades a sheet over 150 MB from the pixel size in its
PNG, JPEG or WebP header without decoding it, and reads large PDFs in
ranges. The worker never opens a source over 300 MB: a finished sheet
placed whole becomes its own print file, which the Kanban offers to approve
as the final, and anything else goes to hand preparation. Files start
uploading as they enter the cart, with progress in the summary, and each
part renews the reservation so slow uploads do not expire. Quotas grow to
50 GB per customer and 500 GB in total; the Swarm config for ClamAV is
renamed because a deployed config cannot change in place.
Verified locally with a 386 MB and a 1.8 GB PNG (scanned, paid, original
as print file), a 2.3 GB PNG (format check) and a disguised 2.3 GB file
(refused).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
When creating the card payment failed, the form's onSubmit rejected with no
message and Mercado Pago's button kept spinning. The page now shows the
reason above the form. A payment Mercado Pago refuses is logged with its
status, message and cause codes (payment_intent_refused) and answered 422
with that reason; other failures log their type.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The number in the Kanban's order panel is now a formatted wa.me link, so a
correction or a question about the artwork can be sent by hand in one
click.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Mercado Pago's form titled both card options "Cartão de crédito ou débito";
the option above it already names the card.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The Integrations tab always said freight was not configured. It now reads
the server's adapter and, with Jadlog on, shows the package weight rule and
the production days the Site prices with.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Going back to home delivery with a CEP already typed, or restoring a saved
cart, now quotes the freight again by itself; before, only pressing Calcular
did. With every case covered, the button is gone.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A complete CEP now looks up its address on the server (ViaCEP, rate
limited, keeping the Site's CSP to its own origin) and fills street,
district, city and state, moving the cursor to the first field left, and
quotes the freight without pressing Calcular. The CEP keeps its mask when
the cart is restored. Freight and its delivery time appear in the order
summary instead of a line under the CEP, the delivery option says it ships
with Jadlog, and the address reminder is a hint rather than an error.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
FREIGHT_ADAPTER=jadlog prices "Receber em casa" through Jadlog's Simulador
de Frete from the order's billed metres and value, adding production days
to Jadlog's delivery time. The package weight is a base plus a weight per
metre from the client, with no default: the adapter refuses to start
without it and without the credentials. The cart re-quotes when the package
changes, and approval quotes again from the server-priced items. The
production stack takes the Jadlog settings, so the read-only probe runs
from the worker's console.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A PIX is created with a 30-minute date_of_expiration, and the PIX page
counts down to it. When it runs out the page says the code expired and
offers a new one. The API keeps one open code per quote: the same code
until it expires, then exactly one new attempt (serialised per quote, with
its own idempotency key), the old one marked expired.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The payment page lists credit card (preselected), debit card and PIX. Each
card option limits Mercado Pago's form to its kind; debit is paid at once.
Card payments ask for 3-D Secure when the issuer requires it, and a
challenge opens the bank's page in a frame, which needs
PAYMENT_CHALLENGE_SOURCES=https: (frames and form posts only). A card left
waiting for that confirmation stops blocking a new attempt after ten
minutes, and a refusal reported by the notification returns the customer to
the payment choice. Written from the documentation; not yet run with a real
debit card.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The payment page puts paying on the left and the order summary on the
right (above it on phones). Card is preselected and paid on the page with
Mercado Pago's form, in the Site's colours and with the order's e-mail;
choosing PIX shows a Pagar button that opens /pagamento/pix with the QR code
and copy-and-paste code, waiting there for the confirmation. A confirmed
payment shows "Pagamento confirmado" with the order number and a button to
the customer's orders. The payment buttons no longer restyle every button
inside the form.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The summary above already shows the total; the line stays only beside the
local stack's simulated payment.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The PIX and card choices appeared under the cart, on the same page as the
customer's details. "Ir para o pagamento" now sends the order and opens
/pagamento, step 3 of the progress bar: the server's order summary, then PIX
or card, each opening below. The cart keeps only the sending progress and its
errors; a changed cart is sent again instead of offering the old quote.
Portal links open the payment page.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The proxy in front of production caches .js and .css for hours. After the
last release the Site got the new index.html with the old site-flow.js,
which wrote to an element the new page no longer has; the error left
"Adicionar ao carrinho" disabled. The web build now addresses every local
script and stylesheet by a hash of its content, replacing the hand-kept
?v= markers, so a new release always loads its own files.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The pickup notice under the delivery options and the invoice and retention
note under the purchase summary are gone. PORTAINER.md records the R2 CORS
policy the browser's direct uploads need: without it the preflight is
refused and checkout fails with a NetworkError before payment.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>